summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2020-09-16 10:32:58 -0700
committerLinux Build Service Account <lnxbuild@localhost>2020-09-16 10:32:58 -0700
commitfdca8623992f3e99208505fbe97a8018b7ddda28 (patch)
tree48625665ca506ef57875aa82ee5e37c03324ebd6
parent1dbbf9a4bf027a8c29b5da6cb2a08f5c148b1440 (diff)
parent6f4ef445a4377b3ff65c772dd06d740d05e99bb9 (diff)
Merge 6f4ef445a4377b3ff65c772dd06d740d05e99bb9 on remote branch
Change-Id: I224ff82129090a7d4060e336eee6faa3ec2808c0
-rw-r--r--Kbuild6
-rw-r--r--core/cds/inc/cds_ieee80211_common.h22
-rw-r--r--core/cds/src/cds_sched.c18
-rw-r--r--core/dp/txrx/ol_tx_desc.c47
-rw-r--r--core/dp/txrx/ol_tx_desc.h24
-rw-r--r--core/dp/txrx/ol_tx_send.c40
-rw-r--r--core/dp/txrx/ol_txrx.c14
-rw-r--r--core/hdd/inc/wlan_hdd_cfg.h49
-rw-r--r--core/hdd/inc/wlan_hdd_ipa.h7
-rw-r--r--core/hdd/inc/wlan_hdd_main.h25
-rw-r--r--core/hdd/inc/wlan_hdd_p2p.h9
-rw-r--r--core/hdd/src/wlan_hdd_assoc.c5
-rw-r--r--core/hdd/src/wlan_hdd_cfg.c56
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c70
-rw-r--r--core/hdd/src/wlan_hdd_driver_ops.c5
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.c3
-rw-r--r--core/hdd/src/wlan_hdd_ipa.c4
-rw-r--r--core/hdd/src/wlan_hdd_main.c13
-rw-r--r--core/hdd/src/wlan_hdd_p2p.c61
-rw-r--r--core/hdd/src/wlan_hdd_power.c15
-rw-r--r--core/hdd/src/wlan_hdd_stats.c415
-rw-r--r--core/hdd/src/wlan_hdd_stats.h8
-rw-r--r--core/mac/inc/ani_system_defs.h33
-rw-r--r--core/mac/inc/qwlan_version.h6
-rw-r--r--core/mac/inc/sir_api.h18
-rw-r--r--core/mac/inc/sir_mac_prot_def.h13
-rw-r--r--core/mac/inc/wni_cfg.h5
-rw-r--r--core/mac/src/cfg/cfg_param_name.c5
-rw-r--r--core/mac/src/cfg/cfg_proc_msg.c7
-rw-r--r--core/mac/src/include/parser_api.h3
-rw-r--r--core/mac/src/pe/include/lim_api.h11
-rw-r--r--core/mac/src/pe/include/lim_global.h33
-rw-r--r--core/mac/src/pe/lim/lim_api.c57
-rw-r--r--core/mac/src/pe/lim/lim_p2p.c8
-rw-r--r--core/mac/src/pe/lim/lim_process_action_frame.c65
-rw-r--r--core/mac/src/pe/lim/lim_process_assoc_req_frame.c382
-rw-r--r--core/mac/src/pe/lim/lim_process_auth_frame.c122
-rw-r--r--core/mac/src/pe/lim/lim_process_message_queue.c164
-rw-r--r--core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c4
-rw-r--r--core/mac/src/pe/lim/lim_process_probe_req_frame.c5
-rw-r--r--core/mac/src/pe/lim/lim_process_sme_req_messages.c22
-rw-r--r--core/mac/src/pe/lim/lim_process_tdls.c103
-rw-r--r--core/mac/src/pe/lim/lim_security_utils.c17
-rw-r--r--core/mac/src/pe/lim/lim_send_management_frames.c42
-rw-r--r--core/mac/src/pe/lim/lim_send_messages.h4
-rw-r--r--core/mac/src/pe/lim/lim_types.h70
-rw-r--r--core/mac/src/pe/nan/nan_datapath.c16
-rw-r--r--core/sap/src/sap_fsm.c9
-rw-r--r--core/sme/inc/csr_api.h7
-rw-r--r--core/sme/inc/sme_api.h16
-rw-r--r--core/sme/src/common/sme_api.c16
-rw-r--r--core/sme/src/common/sme_ft_api.c4
-rw-r--r--core/sme/src/csr/csr_api_roam.c89
-rw-r--r--core/sme/src/csr/csr_inside_api.h25
-rw-r--r--core/sme/src/csr/csr_util.c28
-rw-r--r--core/wma/src/wma_features.c5
56 files changed, 1730 insertions, 600 deletions
diff --git a/Kbuild b/Kbuild
index 14a960c24aa4..6d18e368e14a 100644
--- a/Kbuild
+++ b/Kbuild
@@ -197,6 +197,9 @@ ifeq ($(KERNEL_BUILD), 0)
CONFIG_WLAN_FEATURE_DSRC := y
endif
+#Flag to enable SAE
+CONFIG_WLAN_FEATURE_SAE := y
+
ifneq ($(CONFIG_ROME_IF),sdio)
#Flag to enable DISA
CONFIG_WLAN_FEATURE_DISA := y
@@ -207,9 +210,6 @@ ifneq ($(CONFIG_ROME_IF),sdio)
#Flag to enable GMAC
CONFIG_WLAN_FEATURE_GMAC := y
- #Flag to enable SAE
- CONFIG_WLAN_FEATURE_SAE := y
-
#Flag to enable Fast Path feature
CONFIG_WLAN_FASTPATH := y
diff --git a/core/cds/inc/cds_ieee80211_common.h b/core/cds/inc/cds_ieee80211_common.h
index 1cbaa4c385d3..cc3472d4f69e 100644
--- a/core/cds/inc/cds_ieee80211_common.h
+++ b/core/cds/inc/cds_ieee80211_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011,2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -1631,6 +1631,7 @@ enum {
#define AKM_SUITE_TYPE_FT_PSK 0x04
#define AKM_SUITE_TYPE_SHA256_IEEE8021X 0x05
#define AKM_SUITE_TYPE_SHA256_PSK 0x06
+#define AKM_SUITE_TYPE_SAE 0x08
#define RSN_CAP_PREAUTH 0x01
#define RSN_CAP_PTKSA_REPLAYCOUNTER 0x0c
@@ -1686,6 +1687,25 @@ enum {
#define IEEE80211_RV(v) ((v) & IEEE80211_RATE_VAL)
+#define LE_READ_2(p) \
+ ((uint16_t)\
+ ((((const uint8_t *)(p))[0]) |\
+ (((const uint8_t *)(p))[1] << 8)))
+
+#define LE_READ_4(p) \
+ ((uint32_t)\
+ ((((const uint8_t *)(p))[0]) |\
+ (((const uint8_t *)(p))[1] << 8) | \
+ (((const uint8_t *)(p))[2] << 16) |\
+ (((const uint8_t *)(p))[3] << 24)))
+
+#define BE_READ_4(p) \
+ ((uint32_t)\
+ ((((const uint8_t *)(p))[0] << 24) |\
+ (((const uint8_t *)(p))[1] << 16) |\
+ (((const uint8_t *)(p))[2] << 8) |\
+ (((const uint8_t *)(p))[3])))
+
/*
* AUTH management packets
*
diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c
index a1f8cf6c4ea4..0fa40da3d445 100644
--- a/core/cds/src/cds_sched.c
+++ b/core/cds/src/cds_sched.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -83,6 +83,12 @@ static int cds_mc_thread(void *Arg);
static int cds_ol_mon_thread(void *arg);
static QDF_STATUS cds_alloc_ol_mon_pkt_freeq(p_cds_sched_context pSchedContext);
+static inline
+int cds_set_cpus_allowed_ptr(struct task_struct *task, unsigned long cpu)
+{
+ return set_cpus_allowed_ptr(task, cpumask_of(cpu));
+}
+
#ifdef QCA_CONFIG_SMP
static int cds_ol_rx_thread(void *arg);
static uint32_t affine_cpu;
@@ -95,13 +101,6 @@ static QDF_STATUS cds_alloc_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext);
#define CDS_CPU_CLUSTER_TYPE_LITTLE 0
#define CDS_CPU_CLUSTER_TYPE_PERF 1
-static inline
-int cds_set_cpus_allowed_ptr(struct task_struct *task, unsigned long cpu)
-{
- return set_cpus_allowed_ptr(task, cpumask_of(cpu));
-}
-
-
/**
* cds_sched_find_attach_cpu - find available cores and attach to required core
* @pSchedContext: wlan scheduler context
@@ -618,9 +617,8 @@ OL_MON_THREAD_START_FAILURE:
wake_up_interruptible(&pSchedContext->ol_rx_wait_queue);
/* Wait for RX Thread to exit */
wait_for_completion(&pSchedContext->ol_rx_shutdown);
-#endif
-
OL_RX_THREAD_START_FAILURE:
+#endif
/* Try and force the Main thread controller to exit */
set_bit(MC_SHUTDOWN_EVENT, &pSchedContext->mcEventFlag);
set_bit(MC_POST_EVENT, &pSchedContext->mcEventFlag);
diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c
index 08294827a010..c3f39316ae13 100644
--- a/core/dp/txrx/ol_tx_desc.c
+++ b/core/dp/txrx/ol_tx_desc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -33,6 +33,7 @@
#include <ol_txrx_encap.h> /* OL_TX_RESTORE_HDR, etc */
#endif
#include <ol_txrx.h>
+#include <utils_api.h>
#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
static inline void ol_tx_desc_sanity_checks(struct ol_txrx_pdev_t *pdev,
@@ -1003,4 +1004,48 @@ void ol_tso_num_seg_free(struct ol_txrx_pdev_t *pdev,
pdev->tso_num_seg_pool.num_free++;
qdf_spin_unlock_bh(&pdev->tso_num_seg_pool.tso_num_seg_mutex);
}
+
+bool collect_tso_frags(struct ol_txrx_pdev_t *pdev,
+ struct qdf_tso_seg_elem_t *tso_seg,
+ qdf_nbuf_t netbuf)
+{
+ uint8_t frag_cnt, num_frags = 0;
+ int frag_len = 0;
+ uint32_t tcp_seq_num;
+ uint16_t ip_len;
+
+ qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex);
+
+ if (tso_seg->seg.num_frags > 0)
+ num_frags = tso_seg->seg.num_frags - 1;
+
+ /*Num of frags in a tso seg cannot be less than 2 */
+ if (num_frags < 1) {
+ qdf_print("ERROR: num of frags in tso segment is %d\n",
+ (num_frags + 1));
+ qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
+ return false;
+ }
+
+ tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num;
+ tcp_seq_num = ani_cpu_to_be32(tcp_seq_num);
+
+ ip_len = tso_seg->seg.tso_flags.ip_len;
+ ip_len = ani_cpu_to_be16(ip_len);
+
+ for (frag_cnt = 0; frag_cnt < num_frags; frag_cnt++) {
+ qdf_mem_copy(qdf_nbuf_data(netbuf) + frag_len,
+ tso_seg->seg.tso_frags[frag_cnt].vaddr,
+ tso_seg->seg.tso_frags[frag_cnt].length);
+ frag_len += tso_seg->seg.tso_frags[frag_cnt].length;
+ }
+
+ qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
+
+ qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_PKT_LEN_OFFSET),
+ &ip_len, sizeof(ip_len));
+ qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_TCP_SEQ_NUM_OFFSET),
+ &tcp_seq_num, sizeof(tcp_seq_num));
+ return true;
+}
#endif
diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h
index 6f920e4f0555..b29422ca0496 100644
--- a/core/dp/txrx/ol_tx_desc.h
+++ b/core/dp/txrx/ol_tx_desc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2017, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -239,7 +239,20 @@ void ol_tso_num_seg_free(struct ol_txrx_pdev_t *pdev,
void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev,
struct ol_txrx_msdu_info_t *msdu_info,
bool is_tso_seg_mapping_done);
-
+/**
+ * collect_tso_frags() - collect all TSO fragments
+ * @pdev: The txrx pdev sending the data
+ * @tso_seg: The TSO segment element to be checked
+ * @netbuf: Target netbuf used to store all data from TSO fragments
+ *
+ * This function collects data contained in all TSO fragments related
+ * to a certain TSO segment element and put them into a single netbuf.
+ *
+ * Return: true if TSO fragments are really collected; false otherwise
+ */
+bool collect_tso_frags(struct ol_txrx_pdev_t *pdev,
+ struct qdf_tso_seg_elem_t *tso_seg,
+ qdf_nbuf_t netbuf);
#else
#define ol_tso_alloc_segment(pdev) /*no-op*/
#define ol_tso_free_segment(pdev, tso_seg) /*no-op*/
@@ -247,6 +260,13 @@ void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev,
#define ol_tso_num_seg_free(pdev, tso_num_seg) /*no-op*/
/*no-op*/
#define ol_free_remaining_tso_segs(vdev, msdu_info, is_tso_seg_mapping_done)
+static inline
+bool collect_tso_frags(struct ol_txrx_pdev_t *dev,
+ struct qdf_tso_seg_elem_t *tso_seg,
+ qdf_nbuf_t netbuf)
+{
+ return false;
+}
#endif
/**
diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c
index a1c433499fe2..66860a314865 100644
--- a/core/dp/txrx/ol_tx_send.c
+++ b/core/dp/txrx/ol_tx_send.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -837,6 +837,7 @@ ol_tx_process_mon_tx_completion(
int nbuf_len;
struct qdf_tso_seg_elem_t *tso_seg = NULL;
struct ol_mon_tx_status pkt_tx_status = {0};
+ bool frags_collected = false;
pkt_tx_status.status = status;
pkt_tx_status.tx_retry_cnt = payload->tx_retry_cnt;
@@ -881,44 +882,11 @@ ol_tx_process_mon_tx_completion(
qdf_nbuf_put_tail(netbuf, nbuf_len);
if (tx_desc->pkt_type == OL_TX_FRM_TSO) {
- uint8_t frag_cnt, num_frags = 0;
- int frag_len = 0;
- uint32_t tcp_seq_num;
- uint16_t ip_len;
-
- qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex);
-
- if (tso_seg->seg.num_frags > 0)
- num_frags = tso_seg->seg.num_frags - 1;
-
- /*Num of frags in a tso seg cannot be less than 2 */
- if (num_frags < 1) {
- qdf_print("ERROR: num of frags in tso segment is %d\n",
- (num_frags + 1));
+ frags_collected = collect_tso_frags(pdev, tso_seg, netbuf);
+ if (!frags_collected) {
qdf_nbuf_free(netbuf);
- qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
return;
}
-
- tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num;
- tcp_seq_num = ani_cpu_to_be32(tcp_seq_num);
-
- ip_len = tso_seg->seg.tso_flags.ip_len;
- ip_len = ani_cpu_to_be16(ip_len);
-
- for (frag_cnt = 0; frag_cnt < num_frags; frag_cnt++) {
- qdf_mem_copy(qdf_nbuf_data(netbuf) + frag_len,
- tso_seg->seg.tso_frags[frag_cnt].vaddr,
- tso_seg->seg.tso_frags[frag_cnt].length);
- frag_len += tso_seg->seg.tso_frags[frag_cnt].length;
- }
-
- qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
-
- qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_PKT_LEN_OFFSET),
- &ip_len, sizeof(ip_len));
- qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_TCP_SEQ_NUM_OFFSET),
- &tcp_seq_num, sizeof(tcp_seq_num));
} else {
qdf_mem_copy(qdf_nbuf_data(netbuf),
qdf_nbuf_data(tx_desc->netbuf),
diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c
index 49ca04fccdbd..ecf0bf196a2e 100644
--- a/core/dp/txrx/ol_txrx.c
+++ b/core/dp/txrx/ol_txrx.c
@@ -5608,6 +5608,7 @@ bool ol_txrx_mon_mgmt_process(struct mon_rx_status *txrx_status,
*
* Return: none
*/
+#ifndef CONFIG_HL_SUPPORT
static QDF_STATUS
ol_txrx_convert8023to80311(uint8_t *bssid,
qdf_nbuf_t msdu, void *desc)
@@ -5713,6 +5714,7 @@ ol_txrx_convert8023to80311(uint8_t *bssid,
return status;
}
+#endif
#define SHORT_PREAMBLE 1
#define LONG_PREAMBLE 0
@@ -6114,6 +6116,17 @@ free_buf:
*
* Return: none
*/
+#ifdef CONFIG_HL_SUPPORT
+static void
+ol_txrx_mon_rx_data_cb(void *ppdev, void *nbuf_list, uint8_t vdev_id,
+ uint8_t tid, struct ol_mon_tx_status pkt_tx_status,
+ bool pkt_format)
+{
+ qdf_nbuf_t buf_list = (qdf_nbuf_t)nbuf_list;
+
+ ol_txrx_drop_nbuf_list(buf_list);
+}
+#else
static void
ol_txrx_mon_rx_data_cb(void *ppdev, void *nbuf_list, uint8_t vdev_id,
uint8_t tid, struct ol_mon_tx_status pkt_tx_status,
@@ -6244,6 +6257,7 @@ ol_txrx_mon_rx_data_cb(void *ppdev, void *nbuf_list, uint8_t vdev_id,
free_buf:
drop_count = ol_txrx_drop_nbuf_list(buf_list);
}
+#endif
/**
* ol_txrx_pktcapture_status_map() - map Tx status for data packets
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index 29cbd5a83397..d73f3528d2b5 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -13481,6 +13481,29 @@ enum hw_filter_mode {
/*
* <ini>
+ * enable_sae_for_sap - Enable/Disable SAE support in driver for SAP
+ * @Min: 0
+ * @Max: 1
+ * @Default: 1
+ *
+ * This ini is used to enable/disable SAE support in driver for SAP mode
+ * Driver will process/drop the SAE authentication frames based on this config.
+ *
+ * Related: None
+ *
+ * Supported Feature: SAE
+ * Usage: External
+ *
+ * </ini>
+ */
+
+#define CFG_ENABLE_SAE_FOR_SAP_NAME "enable_sae_for_sap"
+#define CFG_ENABLE_SAE_FOR_SAP_DEFAULT (1)
+#define CFG_ENABLE_SAE_FOR_SAP_MIN (0)
+#define CFG_ENABLE_SAE_FOR_SAP_MAX (1)
+
+/*
+ * <ini>
* chan_width_weightage - Channel Width Weightage to calculate best candidate
* @Min: 0
* @Max: 100
@@ -15560,6 +15583,28 @@ enum hw_filter_mode {
#define CFG_DISABLE_4WAY_HS_OFFLOAD_DEFAULT (0)
/*
+ * <ini>
+ * nb_commands_interval - Used to rate limit nb commands from userspace
+ *
+ * @Min: 0
+ * @Max: 10
+ * Default: 3
+ *
+ * This ini is used to specify the duration in which any supp. nb command from
+ * userspace will not be processed completely in driver. For ex, the default
+ * value of 3 seconds signifies that consecutive commands within that
+ * time will not be processed fully.
+ *
+ * Usage: Internal
+ *
+ * </ini>
+ */
+#define CFG_NB_COMMANDS_RATE_LIMIT "nb_commands_interval"
+#define CFG_NB_COMMANDS_RATE_LIMIT_MIN (0)
+#define CFG_NB_COMMANDS_RATE_LIMIT_MAX (10)
+#define CFG_NB_COMMANDS_RATE_LIMIT_DEFAULT (3)
+
+/*
* Type declarations
*/
@@ -16490,6 +16535,7 @@ struct hdd_config {
uint8_t enable_tx_sch_delay;
#ifdef WLAN_FEATURE_SAE
bool is_sae_enabled;
+ bool enable_sae_for_sap;
#endif
bool enable_rtt_mac_randomization;
bool enable_ftopen;
@@ -16528,6 +16574,7 @@ struct hdd_config {
bool disable_4way_hs_offload;
bool ShortGI80MhzEnable;
bool ShortGI160MhzEnable;
+ uint8_t nb_commands_interval;
};
#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
diff --git a/core/hdd/inc/wlan_hdd_ipa.h b/core/hdd/inc/wlan_hdd_ipa.h
index 9db92f432b71..d66b436aab7b 100644
--- a/core/hdd/inc/wlan_hdd_ipa.h
+++ b/core/hdd/inc/wlan_hdd_ipa.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -100,6 +100,7 @@ bool hdd_ipa_is_fw_wdi_actived(hdd_context_t *hdd_ctx);
#ifndef QCA_LL_TX_FLOW_CONTROL_V2
int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx, bool mcc_mode);
void hdd_ipa_set_mcc_mode(bool mcc_mode);
+void hdd_ipa_mcc_work_handler(struct work_struct *work);
#else
static inline int hdd_ipa_send_mcc_scc_msg(hdd_context_t *hdd_ctx,
bool mcc_mode)
@@ -247,8 +248,8 @@ static inline void hdd_ipa_uc_stat_query(hdd_context_t *hdd_ctx,
*ipa_rx_diff = 0;
}
-static inline void hdd_ipa_uc_stat_request(hdd_adapter_t *adapter,
- uint8_t reason)
+static inline void hdd_ipa_uc_stat_request(hdd_context_t *hdd_ctx,
+ uint8_t reason)
{
}
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 624d8ff03718..5daf67e646e6 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -62,6 +62,29 @@
#define NUM_TX_QUEUES 4
#endif
+/* HDD_IS_RATE_LIMIT_REQ: Macro helper to implement rate limiting
+ * @flag: The flag to determine if limiting is required or not
+ * @rate: The number of seconds within which if multiple commands come, the
+ * flag will be set to true
+ *
+ * If the function in which this macro is used is called multiple times within
+ * "rate" number of seconds, the "flag" will be set to true which can be used
+ * to reject/take appropriate action.
+ */
+#define HDD_IS_RATE_LIMIT_REQ(flag, rate)\
+ do {\
+ static ulong __last_ticks;\
+ ulong __ticks = jiffies;\
+ flag = false; \
+ if (!time_after(__ticks,\
+ __last_ticks + rate * HZ)) {\
+ flag = true; \
+ } \
+ else { \
+ __last_ticks = __ticks;\
+ } \
+ } while (0)
+
/*
* API in_compat_syscall() is introduced in 4.6 kernel to check whether we're
* in a compat syscall or not. It is a new way to query the syscall type, which
diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h
index f71ed6b1847a..0e024442898f 100644
--- a/core/hdd/inc/wlan_hdd_p2p.h
+++ b/core/hdd/inc/wlan_hdd_p2p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -98,9 +98,10 @@ int hdd_set_p2p_ps(struct net_device *dev, void *msgData);
int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command);
int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command);
-void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter,
- uint32_t nFrameLength, uint8_t *pbFrames,
- uint8_t frameType, uint32_t rxChan, int8_t rxRssi);
+void __hdd_indicate_mgmt_frame(hdd_adapter_t *adapter,
+ uint32_t frame_length, uint8_t *frames,
+ uint8_t frame_type, uint32_t rx_chan,
+ int8_t rx_rssi, enum rxmgmt_flags rx_flags);
void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter,
uint32_t scan_id);
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index df3aa8be02c8..dc070c6c7836 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -54,6 +54,7 @@
#include <wlan_logging_sock_svc.h>
#include "wlan_hdd_tsf.h"
#include "wlan_hdd_scan.h"
+#include "wlan_hdd_main.h"
/* These are needed to recognize WPA and RSN suite types */
#define HDD_WPA_OUI_SIZE 4
@@ -2307,10 +2308,10 @@ static void hdd_send_re_assoc_event(struct net_device *dev,
chan_no = pCsrRoamInfo->pBssDesc->channelId;
if (chan_no <= 14)
freq = ieee80211_channel_to_frequency(chan_no,
- NL80211_BAND_2GHZ);
+ HDD_NL80211_BAND_2GHZ);
else
freq = ieee80211_channel_to_frequency(chan_no,
- NL80211_BAND_5GHZ);
+ HDD_NL80211_BAND_5GHZ);
chan = ieee80211_get_channel(pAdapter->wdev.wiphy, freq);
sme_roam_get_connect_profile(hal_handle, pAdapter->sessionId,
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index c47987d70367..11f9f3ca3e89 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -5625,6 +5625,12 @@ struct reg_table_entry g_registry_table[] = {
CFG_IS_SAE_ENABLED_DEFAULT,
CFG_IS_SAE_ENABLED_MIN,
CFG_IS_SAE_ENABLED_MAX),
+ REG_VARIABLE(CFG_ENABLE_SAE_FOR_SAP_NAME, WLAN_PARAM_Integer,
+ struct hdd_config, enable_sae_for_sap,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_SAE_FOR_SAP_DEFAULT,
+ CFG_ENABLE_SAE_FOR_SAP_MIN,
+ CFG_ENABLE_SAE_FOR_SAP_MAX),
#endif
REG_VARIABLE(CFG_BTM_SOLICITED_TIMEOUT, WLAN_PARAM_Integer,
@@ -5854,6 +5860,13 @@ struct reg_table_entry g_registry_table[] = {
CFG_DISABLE_4WAY_HS_OFFLOAD_DEFAULT,
CFG_DISABLE_4WAY_HS_OFFLOAD_MIN,
CFG_DISABLE_4WAY_HS_OFFLOAD_MAX),
+
+ REG_VARIABLE(CFG_NB_COMMANDS_RATE_LIMIT, WLAN_PARAM_Integer,
+ struct hdd_config, nb_commands_interval,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_NB_COMMANDS_RATE_LIMIT_DEFAULT,
+ CFG_NB_COMMANDS_RATE_LIMIT_MIN,
+ CFG_NB_COMMANDS_RATE_LIMIT_MAX),
};
/**
@@ -6795,10 +6808,21 @@ static void hdd_cfg_print_sae(hdd_context_t *hdd_ctx)
CFG_IS_SAE_ENABLED_NAME,
hdd_ctx->config->is_sae_enabled);
}
+
+static void hdd_cfg_print_sae_sap(hdd_context_t *hdd_ctx)
+{
+ hdd_debug("Name = [%s] value = [%u]",
+ CFG_ENABLE_SAE_FOR_SAP_NAME,
+ hdd_ctx->config->enable_sae_for_sap);
+}
#else
static void hdd_cfg_print_sae(hdd_context_t *hdd_ctx)
{
}
+
+static void hdd_cfg_print_sae_sap(hdd_context_t *hdd_ctx)
+{
+}
#endif
#ifdef MWS_COEX
@@ -7895,6 +7919,7 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
CFG_CHANNEL_SELECT_LOGIC_CONC_NAME,
pHddCtx->config->channel_select_logic_conc);
hdd_cfg_print_sae(pHddCtx);
+ hdd_cfg_print_sae_sap(pHddCtx);
hdd_debug("Name = [%s] value = [0x%x]",
CFG_ENABLE_UNIT_TEST_FRAMEWORK_NAME,
pHddCtx->config->is_unit_test_framework_enabled);
@@ -8670,6 +8695,34 @@ static bool hdd_update_vht_cap_in_cfg(hdd_context_t *hdd_ctx)
}
+#ifdef WLAN_FEATURE_SAE
+/**
+ * hdd_update_sae_cfg() - API to update SAE setting to MAC/WNI layer
+ * @hdd_ctx: pointer to hdd_ctx
+ *
+ * This API reads the SAE setting from HDD config structure and updates the
+ * same to MAC/WNI layer.
+ *
+ * Return: true if operation is successful, false otherwise.
+ */
+static inline bool hdd_update_sae_cfg(hdd_context_t *hdd_ctx)
+{
+ bool status = true;
+ if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_SAP_SAE_ENABLED,
+ hdd_ctx->config->enable_sae_for_sap) ==
+ QDF_STATUS_E_FAILURE) {
+ status = false;
+ hdd_err("Couldn't pass on WNI_CFG_SAP_SAE_ENABLED to CCM");
+ }
+ return status;
+}
+#else
+static inline bool hdd_update_sae_cfg(hdd_context_t *hdd_ctx)
+{
+ return true;
+}
+#endif
+
/**
* hdd_update_config_cfg() - API to update INI setting based on hw/fw caps
* @hdd_ctx: pointer to hdd_ctx
@@ -9141,6 +9194,7 @@ bool hdd_update_config_cfg(hdd_context_t *hdd_ctx)
hdd_err("Couldn't pass on WNI_CFG_RATE_FOR_TX_MGMT_5G to CCM");
}
+ status = hdd_update_sae_cfg(hdd_ctx);
return status;
}
#ifdef FEATURE_WLAN_SCAN_PNO
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 6d077856b24c..75254e293084 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -14192,12 +14192,12 @@ static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
if (band_5g) {
for (i = 0; i < hdd_ctx->num_rf_chains; i++)
band_5g->ht_cap.mcs.rx_mask[i] = 0xff;
- /*
- * According to mcs_nss HT MCS parameters highest data
- * rate for Nss = 1 is 150 Mbps
- */
- band_5g->ht_cap.mcs.rx_highest =
- cpu_to_le16(150 * hdd_ctx->num_rf_chains);
+ /*
+ * According to mcs_nss HT MCS parameters highest data
+ * rate for Nss = 1 is 150 Mbps
+ */
+ band_5g->ht_cap.mcs.rx_highest =
+ cpu_to_le16(150 * hdd_ctx->num_rf_chains);
}
}
@@ -21672,13 +21672,56 @@ static int wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
#if defined(WLAN_FEATURE_SAE) && \
defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
+#if defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT)
+/**
+ * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
+ * @adapter: hdd vdev/net_device context
+ * @hHal: Handle to the hal
+ * @params: Pointer to external auth params.
+ *
+ * Extract the PMKID and BSS from external auth params and add to the
+ * PMKSA Cache in CSR.
+ */
+static void
+wlan_hdd_extauth_cache_pmkid(hdd_adapter_t *adapter,
+ tHalHandle hHal,
+ struct cfg80211_external_auth_params *params)
+{
+ tPmkidCacheInfo pmk_cache;
+ QDF_STATUS result;
+
+ if (params->pmkid) {
+ qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
+ qdf_mem_copy(pmk_cache.BSSID.bytes, params->bssid,
+ MAC_ADDR_LEN);
+ qdf_mem_copy(pmk_cache.PMKID, params->pmkid,
+ CSR_RSN_PMKID_SIZE);
+ result = sme_roam_set_pmkid_cache(hHal, adapter->sessionId,
+ &pmk_cache, 1, false);
+ if (!QDF_IS_STATUS_SUCCESS(result))
+ hdd_debug("external_auth: Failed to cache PMKID");
+ }
+}
+#else
+static void
+wlan_hdd_extauth_cache_pmkid(hdd_adapter_t *adapter,
+ tHalHandle hHal,
+ struct cfg80211_external_auth_params *params)
+{}
+#endif
/**
* __wlan_hdd_cfg80211_external_auth() - Handle external auth
+ *
* @wiphy: Pointer to wireless phy
* @dev: net device
- * @params: Pointer to external auth params
- *
+ * @params: Pointer to external auth params.
* Return: 0 on success, negative errno on failure
+ *
+ * Userspace sends status of the external authentication(e.g., SAE) with a peer.
+ * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
+ * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
+ * Userspace may send PMKID in params, which can be used for
+ * further connections.
*/
static int
__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
@@ -21688,6 +21731,7 @@ __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
int ret;
+ struct qdf_mac_addr peer_mac_addr;
if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
hdd_err("Command not allowed in FTM mode");
@@ -21703,8 +21747,14 @@ __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
if (ret)
return ret;
- hdd_debug("external_auth status: %d", params->status);
- sme_handle_sae_msg(hdd_ctx->hHal, adapter->sessionId, params->status);
+ hdd_debug("external_auth status: %d peer mac: " MAC_ADDRESS_STR,
+ params->status, MAC_ADDR_ARRAY(params->bssid));
+ qdf_mem_copy(peer_mac_addr.bytes, params->bssid, MAC_ADDR_LEN);
+
+ wlan_hdd_extauth_cache_pmkid(adapter, hdd_ctx->hHal, params);
+
+ sme_handle_sae_msg(hdd_ctx->hHal, adapter->sessionId, params->status,
+ peer_mac_addr);
return ret;
}
diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c
index 8c4d993b62cb..eb4c8374285a 100644
--- a/core/hdd/src/wlan_hdd_driver_ops.c
+++ b/core/hdd/src/wlan_hdd_driver_ops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -410,10 +410,10 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const struct hif_bus_i
* during load time and during re-init
*/
cds_set_recovery_in_progress(false);
+ hdd_start_complete(0);
if (!reinit) {
cds_set_load_in_progress(false);
cds_set_driver_loaded(true);
- hdd_start_complete(0);
}
hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
@@ -444,6 +444,7 @@ err_init_qdf_ctx:
hdd_remove_pm_qos(dev);
hdd_stop_driver_ops_timer();
+ hdd_start_complete(ret);
mutex_unlock(&hdd_init_deinit_lock);
return check_for_probe_defer(ret);
}
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index f232d18428a7..ff2e4c11667a 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -596,6 +596,7 @@ static int __hdd_hostapd_set_mac_address(struct net_device *dev, void *addr)
hdd_info("Changing MAC to " MAC_ADDRESS_STR " of interface %s ",
MAC_ADDR_ARRAY(mac_addr.bytes),
dev->name);
+ memcpy(&adapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
EXIT();
return 0;
@@ -9023,7 +9024,7 @@ static void hdd_update_beacon_rate(hdd_adapter_t *adapter,
struct cfg80211_bitrate_mask *beacon_rate_mask;
enum nl80211_band band;
- band = params->chandef.chan->band;
+ band = (enum nl80211_band)params->chandef.chan->band;
beacon_rate_mask = &params->beacon_rate;
if (beacon_rate_mask->control[band].legacy) {
adapter->sessionCtx.ap.sapConfig.beacon_tx_rate =
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index f2275fc5e09f..6d1377ef0b02 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -6783,7 +6783,7 @@ void hdd_ipa_set_mcc_mode(bool mcc_mode)
schedule_work(&hdd_ipa->mcc_work);
}
-static void hdd_ipa_mcc_work_handler(struct work_struct *work)
+void hdd_ipa_mcc_work_handler(struct work_struct *work)
{
struct hdd_ipa_priv *hdd_ipa;
hdd_context_t *hdd_ctx;
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 4aa922e2b903..b516be33874a 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -5142,6 +5142,7 @@ QDF_STATUS hdd_stop_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
wlan_hdd_del_station(adapter);
hdd_ipa_flush(hdd_ctx);
+ qdf_flush_work(&hdd_ctx->sap_pre_cac_work);
case QDF_P2P_GO_MODE:
if (hdd_ctx->config->conc_custom_rule1 &&
@@ -5312,7 +5313,7 @@ QDF_STATUS hdd_stop_all_adapters(hdd_context_t *hdd_ctx, bool close_session)
ENTER();
- cds_flush_work(&hdd_ctx->sap_pre_cac_work);
+ qdf_flush_work(&hdd_ctx->sap_pre_cac_work);
cds_flush_sta_ap_intf_work(hdd_ctx);
status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
@@ -5364,7 +5365,7 @@ QDF_STATUS hdd_reset_all_adapters(hdd_context_t *hdd_ctx)
ENTER();
- cds_flush_work(&hdd_ctx->sap_pre_cac_work);
+ qdf_flush_work(&hdd_ctx->sap_pre_cac_work);
cds_flush_sta_ap_intf_work(hdd_ctx);
status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
@@ -8780,7 +8781,8 @@ void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
frame_ind->frameBuf,
frame_ind->frameType,
frame_ind->rxChan,
- frame_ind->rxRssi);
+ frame_ind->rxRssi,
+ frame_ind->rx_flags);
}
status = hdd_get_next_adapter(hdd_ctx,
adapter_node, &next);
@@ -8799,7 +8801,8 @@ void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind)
frame_ind->frameBuf,
frame_ind->frameType,
frame_ind->rxChan,
- frame_ind->rxRssi);
+ frame_ind->rxRssi,
+ frame_ind->rx_flags);
}
/**
@@ -12802,7 +12805,7 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
goto exit;
}
- if (!cds_is_driver_loaded()) {
+ if (!cds_is_driver_loaded() || cds_is_driver_recovering()) {
init_completion(&wlan_start_comp);
rc = wait_for_completion_timeout(&wlan_start_comp,
msecs_to_jiffies(HDD_WLAN_START_WAIT_TIME));
diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c
index cd147f16a76a..88a7a212e170 100644
--- a/core/hdd/src/wlan_hdd_p2p.c
+++ b/core/hdd/src/wlan_hdd_p2p.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -2003,7 +2003,8 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
* When frame to be transmitted is auth mgmt, then trigger
* sme_send_mgmt_tx to send auth frame
*/
- if ((pAdapter->device_mode == QDF_STA_MODE) &&
+ if ((pAdapter->device_mode == QDF_STA_MODE ||
+ pAdapter->device_mode == QDF_SAP_MODE) &&
(type == SIR_MAC_MGMT_FRAME &&
subType == SIR_MAC_MGMT_AUTH)) {
qdf_status = sme_send_mgmt_tx(WLAN_HDD_GET_HAL_CTX(pAdapter),
@@ -3593,15 +3594,62 @@ static uint16_t get_rx_frame_freq_from_chan(uint32_t rx_chan)
HDD_NL80211_BAND_5GHZ);
}
+#if defined(WLAN_FEATURE_SAE) && defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT)
+/**
+ * wlan_hdd_set_rxmgmt_external_auth_flag() - Set the EXTERNAL_AUTH flag
+ * @nl80211_flag: flags to be sent to nl80211 from enum nl80211_rxmgmt_flags
+ *
+ * Set the flag NL80211_RXMGMT_FLAG_EXTERNAL_AUTH if supported.
+ */
+static void
+wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag)
+{
+ *nl80211_flag |= NL80211_RXMGMT_FLAG_EXTERNAL_AUTH;
+}
+#else
+static void
+wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag)
+{
+}
+#endif
+
+/**
+ * wlan_hdd_cfg80211_convert_rxmgmt_flags() - Convert RXMGMT value
+ * @nl80211_flag: Flags to be sent to nl80211 from enum nl80211_rxmgmt_flags
+ * @flag: flags set by driver(SME/PE) from enum rxmgmt_flags
+ *
+ * Convert driver internal RXMGMT flag value to nl80211 defined RXMGMT flag
+ * Return: 0 on success, -EINVAL on invalid value
+ */
+static int
+wlan_hdd_cfg80211_convert_rxmgmt_flags(enum rxmgmt_flags flag,
+ enum nl80211_rxmgmt_flags *nl80211_flag)
+{
+ int ret = -EINVAL;
+
+ if (flag & RXMGMT_FLAG_EXTERNAL_AUTH) {
+ wlan_hdd_set_rxmgmt_external_auth_flag(nl80211_flag);
+ ret = 0;
+ }
+
+ return ret;
+}
+
static void indicate_rx_mgmt_over_nl80211(hdd_adapter_t *adapter,
uint32_t frm_len,
uint8_t *pb_frames, uint16_t freq,
- int8_t rx_rssi)
+ int8_t rx_rssi,
+ enum rxmgmt_flags rx_flags)
{
+ enum nl80211_rxmgmt_flags nl80211_flag = 0;
+
+ if (wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag))
+ hdd_debug("Failed to convert RXMGMT flags :0x%x to nl80211 format",
+ rx_flags);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr,
freq, rx_rssi * 100, pb_frames,
- frm_len, NL80211_RXMGMT_FLAG_ANSWERED);
+ frm_len, NL80211_RXMGMT_FLAG_ANSWERED | nl80211_flag);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr,
freq, rx_rssi * 100, pb_frames,
@@ -3616,7 +3664,8 @@ static void indicate_rx_mgmt_over_nl80211(hdd_adapter_t *adapter,
void __hdd_indicate_mgmt_frame(hdd_adapter_t *adapter, uint32_t frm_len,
uint8_t *pb_frames, uint8_t frame_type,
- uint32_t rx_chan, int8_t rx_rssi)
+ uint32_t rx_chan, int8_t rx_rssi,
+ enum rxmgmt_flags rx_flags)
{
uint16_t freq;
uint8_t type = 0;
@@ -3718,6 +3767,6 @@ indicate:
adapter->sessionId, adapter->dev->ifindex);
indicate_rx_mgmt_over_nl80211(adapter, frm_len, pb_frames,
- freq, rx_rssi);
+ freq, rx_rssi, rx_flags);
}
diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c
index 7e95159b4ae0..74121adc0ddd 100644
--- a/core/hdd/src/wlan_hdd_power.c
+++ b/core/hdd/src/wlan_hdd_power.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -1998,9 +1998,7 @@ int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
struct cfg80211_wowlan *wow)
{
-#ifdef QCA_CONFIG_SMP
#define RX_TLSHIM_SUSPEND_TIMEOUT 200 /* msecs */
-#endif
hdd_context_t *pHddCtx = wiphy_priv(wiphy);
p_cds_sched_context cds_sched_context = get_cds_sched_ctxt();
hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
@@ -2216,8 +2214,8 @@ resume_all:
#ifdef QCA_CONFIG_SMP
complete(&cds_sched_context->ol_resume_rx_event);
pHddCtx->is_ol_rx_thread_suspended = false;
-#endif
resume_mc:
+#endif
complete(&cds_sched_context->ResumeMcEvent);
pHddCtx->isMcThreadSuspended = false;
@@ -2507,6 +2505,7 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
int status;
hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ static bool is_rate_limited;
ENTER();
@@ -2532,10 +2531,14 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
return -EINVAL;
}
+ HDD_IS_RATE_LIMIT_REQ(is_rate_limited,
+ pHddCtx->config->nb_commands_interval);
+
mutex_lock(&pHddCtx->iface_change_lock);
- if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED) {
+ if (pHddCtx->driver_status != DRIVER_MODULES_ENABLED ||
+ is_rate_limited) {
mutex_unlock(&pHddCtx->iface_change_lock);
- hdd_debug("Driver Module not enabled return success");
+ hdd_debug("Modules not enabled/rate limited, use cached stats");
/* Send cached data to upperlayer*/
*dbm = adapter->hdd_stats.ClassA_stat.max_pwr;
return 0;
diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c
index 5b7d009630c1..e2e762c9a69e 100644
--- a/core/hdd/src/wlan_hdd_stats.c
+++ b/core/hdd/src/wlan_hdd_stats.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -35,6 +35,8 @@
#include "wma_api.h"
#include "wma.h"
+#define HDD_LINK_STATS_MAX 5
+
/* 11B, 11G Rate table include Basic rate and Extended rate
* The IDX field is the rate index
* The HI field is the rate when RSSI is strong or being ignored
@@ -125,10 +127,29 @@ static int rssi_mcs_tbl[][10] = {
{-76, -73, -71, -68, -64, -60, -59, -58, -53, -51} /* 80 */
};
-
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
/**
+ * struct hdd_ll_stats - buffered hdd link layer stats
+ * @ll_stats_node: pointer to next stats buffered in scheduler thread context
+ * @result_param_id: Received link layer stats ID
+ * @result: received stats from FW
+ * @more_data: if more stats are pending
+ * @no_of_radios: no of radios
+ * @no_of_peers: no of peers
+ */
+struct hdd_ll_stats {
+ qdf_list_node_t ll_stats_node;
+ u32 result_param_id;
+ void *result;
+ u32 more_data;
+ union {
+ u32 no_of_radios;
+ u32 no_of_peers;
+ } stats_nradio_npeer;
+};
+
+/**
* put_wifi_rate_stat() - put wifi rate stats
* @stats: Pointer to stats context
* @vendor_event: Pointer to vendor event
@@ -861,15 +882,22 @@ static int hdd_llstats_post_radio_stats(hdd_adapter_t *adapter,
QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS,
radiostat->numChannels)) {
hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
+
goto failure;
}
if (radiostat->total_num_tx_power_levels) {
- if (nla_put(vendor_event,
+ ret =
+ nla_put(vendor_event,
QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL,
sizeof(u32) *
radiostat->total_num_tx_power_levels,
- radiostat->tx_time_per_power_level)) {
+ radiostat->tx_time_per_power_level);
+ qdf_mem_free(radiostat->tx_time_per_power_level);
+ radiostat->tx_time_per_power_level = NULL;
+ if (ret) {
+ qdf_mem_free(radiostat->channels);
+ radiostat->channels = NULL;
hdd_err("nla_put fail");
goto failure;
}
@@ -878,6 +906,8 @@ static int hdd_llstats_post_radio_stats(hdd_adapter_t *adapter,
if (radiostat->numChannels) {
ret = hdd_llstats_radio_fill_channels(adapter, radiostat,
vendor_event);
+ qdf_mem_free(radiostat->channels);
+ radiostat->channels = NULL;
if (ret)
goto failure;
}
@@ -954,74 +984,186 @@ static void hdd_link_layer_process_radio_stats(hdd_adapter_t *pAdapter,
EXIT();
}
-/**
- * hdd_ll_process_radio_stats() - Wrapper function for cfg80211/debugfs
- * @adapter: Pointer to device adapter
- * @more_data: More data
- * @data: Pointer to stats data
- * @num_radios: Number of radios
- * @resp_id: Response ID from FW
- *
- * Receiving Link Layer Radio statistics from FW. This function is a wrapper
- * function which calls cfg80211/debugfs functions based on the response ID.
- *
- * Return: None
- */
-static void hdd_ll_process_radio_stats(hdd_adapter_t *adapter,
- uint32_t more_data, void *data, uint32_t num_radio,
- uint32_t resp_id)
+static void hdd_process_ll_stats(tSirLLStatsResults *results,
+ struct hdd_request *request)
{
- if (DEBUGFS_LLSTATS_REQID == resp_id)
- hdd_debugfs_process_radio_stats(adapter, more_data,
- (tpSirWifiRadioStat)data, num_radio);
- else
- hdd_link_layer_process_radio_stats(adapter, more_data,
- (tpSirWifiRadioStat)data, num_radio);
-}
+ struct hdd_ll_stats_priv *priv = hdd_request_priv(request);
+ struct hdd_ll_stats *stats = NULL;
+ size_t stat_size = 0;
-/**
- * hdd_ll_process_iface_stats() - Wrapper function for cfg80211/debugfs
- * @adapter: Pointer to device adapter
- * @data: Pointer to stats data
- * @num_peers: Number of peers
- * @resp_id: Response ID from FW
- *
- * Receiving Link Layer Radio statistics from FW. This function is a wrapper
- * function which calls cfg80211/debugfs functions based on the response ID.
- *
- * Return: None
- */
-static void hdd_ll_process_iface_stats(hdd_adapter_t *adapter,
- void *data, uint32_t num_peers, uint32_t resp_id)
-{
- if (DEBUGFS_LLSTATS_REQID == resp_id)
- hdd_debugfs_process_iface_stats(adapter,
- (tpSirWifiIfaceStat) data, num_peers);
- else
- hdd_link_layer_process_iface_stats(adapter,
- (tpSirWifiIfaceStat) data, num_peers);
+ if (!(priv->request_bitmap & results->paramId))
+ return;
+
+ if (results->paramId & WMI_LINK_STATS_RADIO) {
+ tpSirWifiRadioStat rs_results, stat_result;
+ u64 channel_size = 0, pwr_lvl_size = 0;
+ int i;
+ stats = qdf_mem_malloc(sizeof(*stats));
+ if (!stats)
+ goto exit;
+
+ stat_size = sizeof(tSirWifiRadioStat) * results->num_radio;
+ stats->result_param_id = WMI_LINK_STATS_RADIO;
+ stat_result = qdf_mem_malloc(stat_size);
+ if (!stat_result) {
+ qdf_mem_free(stats);
+ goto exit;
+ }
+ stats->result = stat_result;
+ rs_results = (tpSirWifiRadioStat)results->results;
+ qdf_mem_copy(stats->result, results->results, stat_size);
+ for (i = 0; i < results->num_radio; i++) {
+ channel_size = rs_results->numChannels *
+ sizeof(tSirWifiChannelStats);
+ pwr_lvl_size = sizeof(uint32_t) *
+ rs_results->total_num_tx_power_levels;
+
+ if (rs_results->total_num_tx_power_levels &&
+ rs_results->tx_time_per_power_level) {
+ stat_result->tx_time_per_power_level =
+ qdf_mem_malloc(pwr_lvl_size);
+ if (!stat_result->tx_time_per_power_level) {
+ while (i-- > 0) {
+ stat_result--;
+ qdf_mem_free(stat_result->
+ tx_time_per_power_level);
+ qdf_mem_free(stat_result->
+ channels);
+ }
+ qdf_mem_free(stat_result);
+ qdf_mem_free(stats);
+ goto exit;
+ }
+ qdf_mem_copy(stat_result->tx_time_per_power_level,
+ rs_results->tx_time_per_power_level,
+ pwr_lvl_size);
+ }
+ if (channel_size) {
+ stat_result->channels =
+ qdf_mem_malloc(channel_size);
+ if (!stat_result->channels) {
+ qdf_mem_free(stat_result->
+ tx_time_per_power_level);
+ while (i-- > 0) {
+ stat_result--;
+ qdf_mem_free(stat_result->
+ tx_time_per_power_level);
+ qdf_mem_free(stat_result->
+ channels);
+ }
+ qdf_mem_free(stats->result);
+ qdf_mem_free(stats);
+ goto exit;
+ }
+ qdf_mem_copy(stat_result->channels,
+ rs_results->channels,
+ channel_size);
+ }
+ rs_results++;
+ stat_result++;
+ }
+ stats->stats_nradio_npeer.no_of_radios = results->num_radio;
+ stats->more_data = results->moreResultToFollow;
+ if (!results->moreResultToFollow)
+ priv->request_bitmap &= ~stats->result_param_id;
+ } else if (results->paramId & WMI_LINK_STATS_IFACE) {
+ stats = qdf_mem_malloc(sizeof(*stats));
+ if (!stats)
+ goto exit;
+
+ stats->result_param_id = WMI_LINK_STATS_IFACE;
+ stats->stats_nradio_npeer.no_of_peers = results->num_peers;
+ stats->result = qdf_mem_malloc(sizeof(tSirWifiIfaceStat));
+ if (!stats->result) {
+ qdf_mem_free(stats);
+ goto exit;
+ }
+ qdf_mem_copy(stats->result, results->results,
+ sizeof(tSirWifiIfaceStat));
+ if (!results->num_peers)
+ priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
+ priv->request_bitmap &= ~stats->result_param_id;
+ } else if (results->paramId & WMI_LINK_STATS_ALL_PEER) {
+ tpSirWifiPeerStat peer_stat = (tpSirWifiPeerStat)
+ results->results;
+ tpSirWifiPeerInfo peer_info = NULL;
+ u64 num_rate = 0, peers, rates;
+ int i;
+ stats = qdf_mem_malloc(sizeof(*stats));
+ if (!stats)
+ goto exit;
+
+ peer_info = (tpSirWifiPeerInfo)peer_stat->peerInfo;
+ for (i = 1; i <= peer_stat->numPeers; i++) {
+ num_rate += peer_info->numRate;
+ peer_info = (tpSirWifiPeerInfo)((uint8_t *)
+ peer_info + sizeof(tSirWifiPeerInfo) +
+ (peer_info->numRate *
+ sizeof(tSirWifiRateStat)));
+ }
+
+ peers = sizeof(tSirWifiPeerInfo) * peer_stat->numPeers;
+ rates = sizeof(tSirWifiRateStat) * num_rate;
+ stat_size = sizeof(tSirWifiPeerStat) + peers + rates;
+ stats->result_param_id = WMI_LINK_STATS_ALL_PEER;
+
+ stats->result = qdf_mem_malloc(stat_size);
+ if (!stats->result) {
+ qdf_mem_free(stats);
+ goto exit;
+ }
+
+ qdf_mem_copy(stats->result, results->results, stat_size);
+ stats->more_data = results->moreResultToFollow;
+ if (!results->moreResultToFollow)
+ priv->request_bitmap &= ~stats->result_param_id;
+ } else {
+ hdd_err("INVALID LL_STATS_NOTIFY RESPONSE");
+ }
+ /* send indication to caller thread */
+ if (stats)
+ qdf_list_insert_back(&priv->ll_stats_q, &stats->ll_stats_node);
+
+ if (!priv->request_bitmap)
+exit:
+ hdd_request_complete(request);
}
-/**
- * hdd_ll_process_peer_stats() - Wrapper function for cfg80211/debugfs
- * @adapter: Pointer to device adapter
- * @more_data: More data
- * @data: Pointer to stats data
- * @resp_id: Response ID from FW
- *
- * Receiving Link Layer Radio statistics from FW. This function is a wrapper
- * function which calls cfg80211/debugfs functions based on the response ID.
- *
- * Return: None
- */
-static void hdd_ll_process_peer_stats(hdd_adapter_t *adapter,
- uint32_t more_data, void *data, uint32_t resp_id)
+static void hdd_debugfs_process_ll_stats(hdd_adapter_t *adapter,
+ tSirLLStatsResults *results,
+ struct hdd_request *request)
{
- if (DEBUGFS_LLSTATS_REQID == resp_id)
- hdd_debugfs_process_peer_stats(adapter, data);
- else
- hdd_link_layer_process_peer_stats(adapter, more_data,
- (tpSirWifiPeerStat) data);
+ struct hdd_ll_stats_priv *priv = hdd_request_priv(request);
+
+ if (results->paramId & WMI_LINK_STATS_RADIO) {
+ hdd_debugfs_process_radio_stats(adapter,
+ results->moreResultToFollow,
+ results->results,
+ results->num_radio);
+ if (!results->moreResultToFollow)
+ priv->request_bitmap &= ~(WMI_LINK_STATS_RADIO);
+ } else if (results->paramId & WMI_LINK_STATS_IFACE) {
+ hdd_debugfs_process_iface_stats(adapter, results->results,
+ results->num_peers);
+
+ /* Firmware doesn't send peerstats event if no peers are
+ * connected. HDD should not wait for any peerstats in
+ * this case and return the status to middleware after
+ * receiving iface stats
+ */
+
+ if (!results->num_peers)
+ priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
+ } else if (results->paramId & WMI_LINK_STATS_ALL_PEER) {
+ hdd_debugfs_process_peer_stats(adapter, results->results);
+ if (!results->moreResultToFollow)
+ priv->request_bitmap &= ~(WMI_LINK_STATS_ALL_PEER);
+ } else {
+ hdd_err("INVALID LL_STATS_NOTIFY RESPONSE");
+ }
+
+ if (!priv->request_bitmap)
+ hdd_request_complete(request);
}
/**
@@ -1081,61 +1223,25 @@ void wlan_hdd_cfg80211_link_layer_stats_callback(void *ctx, int indType,
priv = hdd_request_priv(request);
/* validate response received from target */
- if ((priv->request_id != linkLayerStatsResults->rspId) ||
- !(priv->request_bitmap & linkLayerStatsResults->paramId)) {
- hdd_err("Error : Request id %d response id %d request bitmap 0x%x response bitmap 0x%x",
- priv->request_id, linkLayerStatsResults->rspId,
- priv->request_bitmap, linkLayerStatsResults->paramId);
+ if (priv->request_id != linkLayerStatsResults->rspId) {
+ hdd_err("Request id %d response id %d request bitmap 0x%x response bitmap 0x%x",
+ priv->request_id, linkLayerStatsResults->rspId,
+ priv->request_bitmap, linkLayerStatsResults->paramId);
hdd_request_put(request);
return;
}
- if (linkLayerStatsResults->paramId & WMI_LINK_STATS_RADIO) {
- hdd_ll_process_radio_stats(pAdapter,
- linkLayerStatsResults->moreResultToFollow,
- linkLayerStatsResults->results,
- linkLayerStatsResults->num_radio,
- linkLayerStatsResults->rspId);
-
- if (!linkLayerStatsResults->moreResultToFollow)
- priv->request_bitmap &= ~(WMI_LINK_STATS_RADIO);
-
- } else if (linkLayerStatsResults->paramId &
- WMI_LINK_STATS_IFACE) {
- hdd_ll_process_iface_stats(pAdapter,
- linkLayerStatsResults->results,
- linkLayerStatsResults->num_peers,
- linkLayerStatsResults->rspId);
-
- /* Firmware doesn't send peerstats event if no peers are
- * connected. HDD should not wait for any peerstats in
- * this case and return the status to middleware after
- * receiving iface stats
- */
- if (!linkLayerStatsResults->num_peers)
- priv->request_bitmap &=
- ~(WMI_LINK_STATS_ALL_PEER);
- priv->request_bitmap &= ~(WMI_LINK_STATS_IFACE);
-
- } else if (linkLayerStatsResults->
- paramId & WMI_LINK_STATS_ALL_PEER) {
- hdd_ll_process_peer_stats(pAdapter,
- linkLayerStatsResults->moreResultToFollow,
- linkLayerStatsResults->results,
- linkLayerStatsResults->rspId);
-
- if (!linkLayerStatsResults->moreResultToFollow)
- priv->request_bitmap &=
- ~(WMI_LINK_STATS_ALL_PEER);
-
- } else {
- hdd_err("INVALID LL_STATS_NOTIFY RESPONSE");
+ if (linkLayerStatsResults->rspId == DEBUGFS_LLSTATS_REQID) {
+ hdd_debugfs_process_ll_stats(pAdapter,
+ linkLayerStatsResults,
+ request);
+ } else {
+ qdf_spin_lock(&priv->ll_stats_lock);
+ if (priv->request_bitmap)
+ hdd_process_ll_stats(linkLayerStatsResults, request);
+ qdf_spin_unlock(&priv->ll_stats_lock);
}
- /* complete response event if all requests are completed */
- if (!priv->request_bitmap)
- hdd_request_complete(request);
-
hdd_request_put(request);
break;
}
@@ -1312,6 +1418,46 @@ nla_policy
[QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK] = {.type = NLA_U32}
};
+static void wlan_hdd_handle_ll_stats(hdd_adapter_t *adapter,
+ struct hdd_ll_stats *stats,
+ int ret)
+{
+ switch (stats->result_param_id) {
+ case WMI_LINK_STATS_RADIO:
+ {
+ tpSirWifiRadioStat radio_stat = stats->result;
+ int i, num_radio = stats->stats_nradio_npeer.no_of_radios;
+
+ if (ret == -ETIMEDOUT) {
+ for (i = 0; i < num_radio; i++) {
+ if (radio_stat->numChannels)
+ qdf_mem_free(radio_stat->channels);
+ if (radio_stat->total_num_tx_power_levels)
+ qdf_mem_free(radio_stat->
+ tx_time_per_power_level);
+ radio_stat++;
+ }
+ return;
+ }
+ hdd_link_layer_process_radio_stats(adapter, stats->more_data,
+ radio_stat, num_radio);
+ }
+ break;
+ case WMI_LINK_STATS_IFACE:
+ hdd_link_layer_process_iface_stats(adapter, stats->result,
+ stats->stats_nradio_npeer.
+ no_of_peers);
+ break;
+ case WMI_LINK_STATS_ALL_PEER:
+ hdd_link_layer_process_peer_stats(adapter,
+ stats->more_data,
+ stats->result);
+ break;
+ default:
+ hdd_err("not requested event");
+ }
+}
+
/**
* wlan_hdd_send_ll_stats_req() - send LL stats request
* @hdd_ctx: pointer to hdd context
@@ -1319,12 +1465,16 @@ nla_policy
*
* Return: 0 if success, non-zero if failure
*/
-static int wlan_hdd_send_ll_stats_req(hdd_context_t *hdd_ctx,
+static int wlan_hdd_send_ll_stats_req(hdd_adapter_t *adapter,
tSirLLStatsGetReq *req)
{
int ret = 0;
- struct hdd_ll_stats_priv *priv = NULL;
+ struct hdd_ll_stats_priv *priv;
+ struct hdd_ll_stats *stats = NULL;
struct hdd_request *request = NULL;
+ qdf_list_node_t *ll_node;
+ QDF_STATUS status;
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
void *cookie = NULL;
static const struct hdd_request_params params = {
.priv_size = sizeof(*priv),
@@ -1345,6 +1495,8 @@ static int wlan_hdd_send_ll_stats_req(hdd_context_t *hdd_ctx,
priv->request_id = req->reqId;
priv->request_bitmap = req->paramIdMask;
+ qdf_spinlock_create(&priv->ll_stats_lock);
+ qdf_list_create(&priv->ll_stats_q, HDD_LINK_STATS_MAX);
if (QDF_STATUS_SUCCESS !=
sme_ll_stats_get_req(hdd_ctx->hHal, req, cookie)) {
@@ -1352,18 +1504,33 @@ static int wlan_hdd_send_ll_stats_req(hdd_context_t *hdd_ctx,
ret = -EINVAL;
goto exit;
}
-
ret = hdd_request_wait_for_response(request);
if (ret) {
hdd_err("Target response timed out request id %d request bitmap 0x%x",
priv->request_id, priv->request_bitmap);
+ qdf_spin_lock(&priv->ll_stats_lock);
+ priv->request_bitmap = 0;
+ qdf_spin_unlock(&priv->ll_stats_lock);
ret = -ETIMEDOUT;
- goto exit;
}
- EXIT();
-
+ qdf_spin_lock(&priv->ll_stats_lock);
+ status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node);
+ qdf_spin_unlock(&priv->ll_stats_lock);
+ while (QDF_IS_STATUS_SUCCESS(status)) {
+ stats = qdf_container_of(ll_node, struct hdd_ll_stats,
+ ll_stats_node);
+ wlan_hdd_handle_ll_stats(adapter, stats, ret);
+ qdf_mem_free(stats->result);
+ qdf_mem_free(stats);
+ qdf_spin_lock(&priv->ll_stats_lock);
+ status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node);
+ qdf_spin_unlock(&priv->ll_stats_lock);
+ }
+ qdf_list_destroy(&priv->ll_stats_q);
exit:
+ EXIT();
hdd_request_put(request);
+
return ret;
}
@@ -1406,7 +1573,7 @@ int wlan_hdd_ll_stats_get(hdd_adapter_t *adapter, uint32_t req_id,
}
rtnl_lock();
- ret = wlan_hdd_send_ll_stats_req(hdd_ctx, &get_req);
+ ret = wlan_hdd_send_ll_stats_req(adapter, &get_req);
rtnl_unlock();
if (0 != ret)
hdd_err("Send LL stats req failed, id:%u, mask:%d, session:%d",
@@ -1493,7 +1660,7 @@ __wlan_hdd_cfg80211_ll_stats_get(struct wiphy *wiphy,
return -EINVAL;
}
- ret = wlan_hdd_send_ll_stats_req(pHddCtx, &LinkLayerStatsGetReq);
+ ret = wlan_hdd_send_ll_stats_req(pAdapter, &LinkLayerStatsGetReq);
if (0 != ret) {
hdd_err("Failed to send LL stats request (id:%u)",
LinkLayerStatsGetReq.reqId);
diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h
index 496106f682a3..48e9b05ed200 100644
--- a/core/hdd/src/wlan_hdd_stats.h
+++ b/core/hdd/src/wlan_hdd_stats.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018,2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -81,13 +81,17 @@ struct index_data_rate_type {
/**
* struct hdd_ll_stats_priv - hdd link layer stats private
- *
+ * @ll_stats: head to different link layer stats received in scheduler
+ * thread context
* @request_id: userspace-assigned link layer stats request id
* @request_bitmap: userspace-assigned link layer stats request bitmap
+ * @ll_stats_lock: Lock to serially access request_bitmap
*/
struct hdd_ll_stats_priv {
+ qdf_list_t ll_stats_q;
uint32_t request_id;
uint32_t request_bitmap;
+ qdf_spinlock_t ll_stats_lock;
};
/*
diff --git a/core/mac/inc/ani_system_defs.h b/core/mac/inc/ani_system_defs.h
index 9cf44ca3f203..d6b938bc4683 100644
--- a/core/mac/inc/ani_system_defs.h
+++ b/core/mac/inc/ani_system_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -200,4 +200,35 @@ typedef struct sBcnReportFields {
uint16_t CapabilityInfo;
} qdf_packed tBcnReportFields, *tpBcnReportFields;
+enum ani_akm_type {
+ ANI_AKM_TYPE_NONE,
+ ANI_AKM_TYPE_RSN,
+ ANI_AKM_TYPE_RSN_PSK,
+ ANI_AKM_TYPE_FT_RSN,
+ ANI_AKM_TYPE_FT_RSN_PSK,
+ ANI_AKM_TYPE_RSN_PSK_SHA256,
+ ANI_AKM_TYPE_RSN_8021X_SHA256,
+#ifdef WLAN_FEATURE_SAE
+ ANI_AKM_TYPE_SAE,
+ ANI_AKM_TYPE_FT_SAE,
+#endif
+ ANI_AKM_TYPE_SUITEB_EAP_SHA256,
+ ANI_AKM_TYPE_SUITEB_EAP_SHA384,
+ ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384,
+ ANI_AKM_TYPE_FILS_SHA256,
+ ANI_AKM_TYPE_FILS_SHA384,
+ ANI_AKM_TYPE_FT_FILS_SHA256,
+ ANI_AKM_TYPE_FT_FILS_SHA384,
+ ANI_AKM_TYPE_OWE,
+#ifdef FEATURE_WLAN_ESE
+ ANI_AKM_TYPE_CCKM,
+#endif
+ ANI_AKM_TYPE_OSEN,
+ ANI_AKM_TYPE_DPP_RSN,
+ ANI_AKM_TYPE_WPA,
+ ANI_AKM_TYPE_WPA_PSK,
+ ANI_NUM_OF_SUPPORT_AKM_TYPE,
+ ANI_AKM_TYPE_UNKNOWN = 0xff,
+};
+
#endif /* __ANI_SYSTEM_DEFS_H */
diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h
index 7cea62f543b2..a007c98b67f9 100644
--- a/core/mac/inc/qwlan_version.h
+++ b/core/mac/inc/qwlan_version.h
@@ -32,9 +32,9 @@
#define QWLAN_VERSION_MAJOR 5
#define QWLAN_VERSION_MINOR 1
#define QWLAN_VERSION_PATCH 1
-#define QWLAN_VERSION_EXTRA "R"
-#define QWLAN_VERSION_BUILD 76
+#define QWLAN_VERSION_EXTRA "U"
+#define QWLAN_VERSION_BUILD 77
-#define QWLAN_VERSIONSTR "5.1.1.76R"
+#define QWLAN_VERSIONSTR "5.1.1.77U"
#endif /* QWLAN_VERSION_H */
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 3fdc2869f661..9f870a04e937 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -1536,6 +1536,7 @@ typedef struct sSirSmeAssocInd {
tDot11fIEHTCaps HTCaps;
tDot11fIEVHTCaps VHTCaps;
tSirMacCapabilityInfo capability_info;
+ bool is_sae_authenticated;
} tSirSmeAssocInd, *tpSirSmeAssocInd;
/* / Definition for Association confirm */
@@ -1549,6 +1550,7 @@ typedef struct sSirSmeAssocCnf {
uint16_t aid;
struct qdf_mac_addr alternate_bssid;
uint8_t alternateChannelId;
+ tSirMacStatusCodes mac_status_code;
} tSirSmeAssocCnf, *tpSirSmeAssocCnf;
/* / Enum definition for Wireless medium status change codes */
@@ -3025,12 +3027,24 @@ typedef struct sSirKeepAliveReq {
uint8_t sessionId;
} tSirKeepAliveReq, *tpSirKeepAliveReq;
+/**
+ * enum rxmgmt_flags - flags for received management frame.
+ * @RXMGMT_FLAG_NONE: Default value to indicate no flags are set.
+ * @RXMGMT_FLAG_EXTERNAL_AUTH: frame can be used for external authentication
+ * by upper layers.
+ */
+enum rxmgmt_flags {
+ RXMGMT_FLAG_NONE,
+ RXMGMT_FLAG_EXTERNAL_AUTH = 1 << 1,
+};
+
typedef struct sSirSmeMgmtFrameInd {
uint16_t frame_len;
uint32_t rxChan;
uint8_t sessionId;
uint8_t frameType;
int8_t rxRssi;
+ enum rxmgmt_flags rx_flags;
uint8_t frameBuf[1]; /* variable */
} tSirSmeMgmtFrameInd, *tpSirSmeMgmtFrameInd;
@@ -8581,12 +8595,14 @@ struct sir_sae_info {
* @length: message length
* @session_id: SME session id
* @sae_status: SAE status, 0: Success, Non-zero: Failure.
+ * @peer_mac_addr: peer MAC address
*/
struct sir_sae_msg {
uint16_t message_type;
uint16_t length;
uint16_t session_id;
uint8_t sae_status;
+ tSirMacAddr peer_mac_addr;
};
/**
diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h
index 5f23432ec24b..8e15026a07b8 100644
--- a/core/mac/inc/sir_mac_prot_def.h
+++ b/core/mac/inc/sir_mac_prot_def.h
@@ -653,7 +653,8 @@
#define SIR_MAX_BEACON_SIZE 512
#define SIR_MAX_PROBE_RESP_SIZE 512
-/* / Status Code (present in Management response frames) enum */
+/* Status Code (present in Management response frames) enum */
+/* (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46) */
typedef enum eSirMacStatusCodes {
eSIR_MAC_SUCCESS_STATUS = 0, /* Reserved */
@@ -698,7 +699,9 @@ typedef enum eSirMacStatusCodes {
eSIR_MAC_DSSS_OFDM_NOT_SUPPORTED_STATUS = 26, /* Association denied due to requesting station not supporting the DSSS-OFDM option */
/* reserved 27-29 */
eSIR_MAC_TRY_AGAIN_LATER = 30, /* Association request rejected temporarily, try again later */
- /* reserved 31 */
+#ifdef WLAN_FEATURE_11W
+ eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION_STATUS = 31, /* Robust management frames policy violation */
+#endif
eSIR_MAC_QOS_UNSPECIFIED_FAILURE_STATUS = 32, /* Unspecified, QoS-related failure */
eSIR_MAC_QAP_NO_BANDWIDTH_STATUS = 33, /* Association denied because QoS AP has insufficient bandwidth to handle another */
/* QoS STA */
@@ -731,9 +734,9 @@ typedef enum eSirMacStatusCodes {
eSIR_MAC_DEST_STA_NOT_QSTA_STATUS = 50, /* The Destination STA is not a QoS STA */
eSIR_MAC_INVALID_LISTEN_INTERVAL_STATUS = 51, /* Association denied because the ListenInterval is too large */
- eSIR_MAC_DSSS_CCK_RATE_MUST_SUPPORT_STATUS = 52, /* FIXME: */
- eSIR_MAC_DSSS_CCK_RATE_NOT_SUPPORT_STATUS = 53,
- eSIR_MAC_PSMP_CONTROLLED_ACCESS_ONLY_STATUS = 54,
+ eSIR_MAC_INVALID_FT_ACTION_FRAME_COUNT = 52,
+ eSIR_MAC_INVALID_PMKID = 53,
+
#ifdef FEATURE_WLAN_ESE
eSIR_MAC_ESE_UNSPECIFIED_QOS_FAILURE_STATUS = 200, /* ESE-Unspecified, QoS related failure in (Re)Assoc response frames */
eSIR_MAC_ESE_TSPEC_REQ_REFUSED_STATUS = 201, /* ESE-TSPEC request refused due to AP's policy configuration in AddTs Rsp, (Re)Assoc Rsp. */
diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h
index 6a436fc3c708..e893c3af2cd0 100644
--- a/core/mac/inc/wni_cfg.h
+++ b/core/mac/inc/wni_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -255,6 +255,9 @@ enum {
WNI_CFG_EDCA_ETSI_ACBE,
WNI_CFG_EDCA_ETSI_ACVI,
WNI_CFG_EDCA_ETSI_ACVO,
+#ifdef WLAN_FEATURE_SAE
+ WNI_CFG_SAP_SAE_ENABLED,
+#endif
/* Any new items to be added should be above this strictly */
CFG_PARAM_MAX_NUM
};
diff --git a/core/mac/src/cfg/cfg_param_name.c b/core/mac/src/cfg/cfg_param_name.c
index d960a6219657..486632ec660c 100644
--- a/core/mac/src/cfg/cfg_param_name.c
+++ b/core/mac/src/cfg/cfg_param_name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -337,4 +337,7 @@ unsigned char *g_cfg_param_name[] = {
(unsigned char *)"EDCA_ETSI_ACBE",
(unsigned char *)"EDCA_ETSI_ACVI",
(unsigned char *)"EDCA_ETSI_ACVO",
+#ifdef WLAN_FEATURE_SAE
+ (unsigned char *)"SAP_SAE_ENABLED",
+#endif
};
diff --git a/core/mac/src/cfg/cfg_proc_msg.c b/core/mac/src/cfg/cfg_proc_msg.c
index acc40f750048..053490659e89 100644
--- a/core/mac/src/cfg/cfg_proc_msg.c
+++ b/core/mac/src/cfg/cfg_proc_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -1188,6 +1188,11 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = {
{WNI_CFG_EDCA_ETSI_ACVO,
CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_RESTART,
0, 0, 0},
+#ifdef WLAN_FEATURE_SAE
+ {WNI_CFG_SAP_SAE_ENABLED,
+ CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
+ 0, 1, 1},
+#endif
};
diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h
index 4a65b276bda3..1df8250a20de 100644
--- a/core/mac/src/include/parser_api.h
+++ b/core/mac/src/include/parser_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -425,6 +425,7 @@ typedef struct sSirAssocReq {
tDot11fIEExtCap ExtCap;
tDot11fIEvendor_vht_ie vendor_vht_ie;
tDot11fIEhs20vendor_ie hs20vendor_ie;
+ bool is_sae_authenticated;
} tSirAssocReq, *tpSirAssocReq;
/* / Association Response structure (one day to be replaced by */
diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h
index ec7ca33f8b04..013a077d8b28 100644
--- a/core/mac/src/pe/include/lim_api.h
+++ b/core/mac/src/pe/include/lim_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -322,5 +322,14 @@ static inline void lim_fill_join_rsp_ht_caps(tpPESession session,
#endif
QDF_STATUS lim_update_ext_cap_ie(tpAniSirGlobal mac_ctx,
uint8_t *ie_data, uint8_t *local_ie_buf, uint16_t *local_ie_len);
+
+/**
+ * lim_translate_rsn_oui_to_akm_type() - translate RSN OUI to AKM type
+ * @auth_suite: auth suite
+ *
+ * Return: AKM type
+ */
+enum ani_akm_type lim_translate_rsn_oui_to_akm_type(uint8_t auth_suite[4]);
+
/************************************************************/
#endif /* __LIM_API_H */
diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h
index f455308936d4..d2bb3480de81 100644
--- a/core/mac/src/pe/include/lim_global.h
+++ b/core/mac/src/pe/include/lim_global.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -298,6 +298,33 @@ typedef struct sLimMlmOemDataRsp {
} tLimMlmOemDataRsp, *tpLimMlmOemDataRsp;
#endif
+/* Forward declarations */
+struct sSirAssocReq;
+struct sDphHashNode;
+
+/* struct lim_assoc_data - Assoc data to be cached to defer association
+ * indication to SME
+ * @present: Indicates whether assoc data is present or not
+ * @sub_type: Indicates whether it is Association Request(=0) or Reassociation
+ * Request(=1) frame
+ * @hdr: MAC header
+ * @assoc_req: pointer to parsed ASSOC/REASSOC Request frame
+ * @pmf_connection: flag indicating pmf connection
+ * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above
+ * @dup_entry: flag indicating if duplicate entry found
+ * @sta_ds: station dph entry
+ */
+struct lim_assoc_data {
+ bool present;
+ uint8_t sub_type;
+ tSirMacMgmtHdr hdr;
+ struct sSirAssocReq *assoc_req;
+ bool pmf_connection;
+ bool assoc_req_copied;
+ bool dup_entry;
+ struct sDphHashNode *sta_ds;
+};
+
/* Pre-authentication structure definition */
typedef struct tLimPreAuthNode {
struct tLimPreAuthNode *next;
@@ -313,6 +340,10 @@ typedef struct tLimPreAuthNode {
TX_TIMER timer;
uint16_t seq_num;
unsigned long timestamp;
+ /* keeping copy of association request received, this is
+ * to defer the association request processing
+ */
+ struct lim_assoc_data assoc_req;
} tLimPreAuthNode, *tpLimPreAuthNode;
/* Pre-authentication table definition */
diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c
index 58f7190fb4ae..24c0a037b70b 100644
--- a/core/mac/src/pe/lim/lim_api.c
+++ b/core/mac/src/pe/lim/lim_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -2555,3 +2555,58 @@ QDF_STATUS lim_update_ext_cap_ie(tpAniSirGlobal mac_ctx,
return QDF_STATUS_SUCCESS;
}
+#define LIM_RSN_OUI_SIZE 4
+
+struct rsn_oui_akm_type_map {
+ enum ani_akm_type akm_type;
+ uint8_t rsn_oui[LIM_RSN_OUI_SIZE];
+};
+
+static const struct rsn_oui_akm_type_map rsn_oui_akm_type_mapping_table[] = {
+ {ANI_AKM_TYPE_RSN, {0x00, 0x0F, 0xAC, 0x01} },
+ {ANI_AKM_TYPE_RSN_PSK, {0x00, 0x0F, 0xAC, 0x02} },
+ {ANI_AKM_TYPE_FT_RSN, {0x00, 0x0F, 0xAC, 0x03} },
+ {ANI_AKM_TYPE_FT_RSN_PSK, {0x00, 0x0F, 0xAC, 0x04} },
+ {ANI_AKM_TYPE_RSN_8021X_SHA256, {0x00, 0x0F, 0xAC, 0x05} },
+ {ANI_AKM_TYPE_RSN_PSK_SHA256, {0x00, 0x0F, 0xAC, 0x06} },
+#ifdef WLAN_FEATURE_SAE
+ {ANI_AKM_TYPE_SAE, {0x00, 0x0F, 0xAC, 0x08} },
+ {ANI_AKM_TYPE_FT_SAE, {0x00, 0x0F, 0xAC, 0x09} },
+#endif
+ {ANI_AKM_TYPE_SUITEB_EAP_SHA256, {0x00, 0x0F, 0xAC, 0x0B} },
+ {ANI_AKM_TYPE_SUITEB_EAP_SHA384, {0x00, 0x0F, 0xAC, 0x0C} },
+ {ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384, {0x00, 0x0F, 0xAC, 0x0D} },
+ {ANI_AKM_TYPE_FILS_SHA256, {0x00, 0x0F, 0xAC, 0x0E} },
+ {ANI_AKM_TYPE_FILS_SHA384, {0x00, 0x0F, 0xAC, 0x0F} },
+ {ANI_AKM_TYPE_FT_FILS_SHA256, {0x00, 0x0F, 0xAC, 0x10} },
+ {ANI_AKM_TYPE_FT_FILS_SHA384, {0x00, 0x0F, 0xAC, 0x11} },
+ {ANI_AKM_TYPE_OWE, {0x00, 0x0F, 0xAC, 0x12} },
+#ifdef FEATURE_WLAN_ESE
+ {ANI_AKM_TYPE_CCKM, {0x00, 0x40, 0x96, 0x00} },
+#endif
+ {ANI_AKM_TYPE_OSEN, {0x50, 0x6F, 0x9A, 0x01} },
+ {ANI_AKM_TYPE_DPP_RSN, {0x50, 0x6F, 0x9A, 0x02} },
+ {ANI_AKM_TYPE_WPA, {0x00, 0x50, 0xF2, 0x01} },
+ {ANI_AKM_TYPE_WPA_PSK, {0x00, 0x50, 0xF2, 0x02} },
+ /* Add akm type above here */
+ {ANI_AKM_TYPE_UNKNOWN, {0} },
+};
+
+enum ani_akm_type lim_translate_rsn_oui_to_akm_type(uint8_t auth_suite[4])
+{
+ const struct rsn_oui_akm_type_map *map;
+ enum ani_akm_type akm_type;
+
+ map = rsn_oui_akm_type_mapping_table;
+ while (true) {
+ akm_type = map->akm_type;
+ if ((akm_type == ANI_AKM_TYPE_UNKNOWN) ||
+ (qdf_mem_cmp(auth_suite, map->rsn_oui, 4) == 0))
+ break;
+ map++;
+ }
+
+ pe_debug("akm_type: %d", akm_type);
+
+ return akm_type;
+}
diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c
index 121f18145831..32b6745c1d21 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-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -374,7 +374,8 @@ void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, QDF_STATUS status, uint32_t *dat
void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
uint8_t *frame, uint32_t frameLen,
uint16_t sessionId, uint32_t rxChannel,
- tpPESession psessionEntry, int8_t rxRssi)
+ tpPESession session_entry,
+ int8_t rx_rssi, enum rxmgmt_flags rx_flags)
{
tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL;
uint16_t length;
@@ -397,8 +398,9 @@ void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
pSirSmeMgmtFrame->frame_len = frameLen;
pSirSmeMgmtFrame->sessionId = sessionId;
pSirSmeMgmtFrame->frameType = frameType;
- pSirSmeMgmtFrame->rxRssi = rxRssi;
+ pSirSmeMgmtFrame->rxRssi = rx_rssi;
pSirSmeMgmtFrame->rxChan = rxChannel;
+ pSirSmeMgmtFrame->rx_flags = rx_flags;
qdf_mem_zero(pSirSmeMgmtFrame->frameBuf, frameLen);
qdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen);
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 402f42b04e46..5063c5fbc390 100644
--- a/core/mac/src/pe/lim/lim_process_action_frame.c
+++ b/core/mac/src/pe/lim/lim_process_action_frame.c
@@ -1096,10 +1096,11 @@ static void __lim_process_qos_map_configure_frame(tpAniSirGlobal mac_ctx,
return;
}
lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
- (uint8_t *) mac_hdr,
- frame_len + sizeof(tSirMacMgmtHdr), 0,
- WMA_GET_RX_CH(rx_pkt_info), session,
- WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info));
+ (uint8_t *)mac_hdr,
+ frame_len + sizeof(tSirMacMgmtHdr), 0,
+ WMA_GET_RX_CH(rx_pkt_info), session,
+ WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
+ RXMGMT_FLAG_NONE);
}
#ifdef ANI_SUPPORT_11H
@@ -1318,9 +1319,10 @@ __lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
/* 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,
- WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo));
+ frameLen + sizeof(tSirMacMgmtHdr), 0,
+ WMA_GET_RX_CH(pRxPacketInfo), psessionEntry,
+ WMA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo),
+ RXMGMT_FLAG_NONE);
frm = qdf_mem_malloc(sizeof(*frm));
if (frm == NULL) {
@@ -1555,7 +1557,7 @@ static void __lim_process_sa_query_response_action_frame(tpAniSirGlobal pMac,
WMA_GET_RX_CH(pRxPacketInfo),
psessionEntry,
WMA_GET_RX_RSSI_NORMALIZED(
- pRxPacketInfo));
+ pRxPacketInfo), RXMGMT_FLAG_NONE);
return;
}
@@ -1686,7 +1688,7 @@ static void lim_process_action_vendor_specific(tpAniSirGlobal mac_ctx,
sizeof(tSirMacMgmtHdr), session_id,
WMA_GET_RX_CH(pkt_info), session,
WMA_GET_RX_RSSI_NORMALIZED(
- pkt_info));
+ pkt_info), RXMGMT_FLAG_NONE);
} else {
pe_debug("Unhandled public action frame (Vendor specific) OUI: %x %x %x %x",
action_hdr->Oui[0],
@@ -1870,7 +1872,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
frame_len + sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info),
- session, rssi);
+ session, rssi, RXMGMT_FLAG_NONE);
break;
default:
pe_debug("Action ID: %d not handled in WNM category",
@@ -1960,7 +1962,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
WMA_GET_RX_CH(rx_pkt_info),
session,
WMA_GET_RX_RSSI_NORMALIZED(
- rx_pkt_info));
+ rx_pkt_info), RXMGMT_FLAG_NONE);
} else {
pe_debug("Dropping the vendor specific action frame beacause of (WES Mode not enabled (WESMODE: %d) or OUI mismatch (%02x %02x %02x) or not received with SelfSta address) system role: %d",
IS_WES_MODE_ENABLED(mac_ctx),
@@ -2006,7 +2008,8 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
frame_len + sizeof(tSirMacMgmtHdr),
session->smeSessionId,
WMA_GET_RX_CH(rx_pkt_info), session,
- WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info));
+ WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
+ RXMGMT_FLAG_NONE);
break;
default:
@@ -2072,7 +2075,7 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
WMA_GET_RX_CH(rx_pkt_info),
session,
WMA_GET_RX_RSSI_NORMALIZED(
- rx_pkt_info));
+ rx_pkt_info), RXMGMT_FLAG_NONE);
break;
}
case SIR_MAC_ACTION_PROT_DUAL_PUB:
@@ -2089,7 +2092,8 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
mac_hdr->fc.subType, (uint8_t *) mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr),
session->smeSessionId,
- WMA_GET_RX_CH(rx_pkt_info), session, rssi);
+ WMA_GET_RX_CH(rx_pkt_info), session, rssi,
+ RXMGMT_FLAG_NONE);
break;
default:
pe_warn("Unhandled - Protected Dual Public Action");
@@ -2104,30 +2108,23 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx,
}
/**
- * lim_process_action_frame_no_session
+ * lim_process_action_frame_no_session() - action frame handler
+ * @mac - Pointer to Global MAC structure
+ * @bd - A pointer to Buffer descriptor + associated PDUs
*
- ***FUNCTION:
* This function is called by limProcessMessageQueue() upon
* Action frame reception and no session.
* Currently only public action frames can be received from
* a non-associated station.
*
- ***LOGIC:
- *
- ***ASSUMPTIONS:
- *
- ***NOTE:
- *
- * @param pMac - Pointer to Global MAC structure
- * @param *pBd - A pointer to Buffer descriptor + associated PDUs
* @return None
*/
-void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd)
+void lim_process_action_frame_no_session(tpAniSirGlobal mac, uint8_t *bd)
{
- 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);
+ tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(bd);
+ uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(bd);
+ uint8_t *pBody = WMA_GET_RX_MPDU_DATA(bd);
tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) pBody;
tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific;
@@ -2146,7 +2143,7 @@ void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd)
vendor_specific =
(tpSirMacVendorSpecificPublicActionFrameHdr)
action_hdr;
- lim_process_action_vendor_specific(pMac, pBd,
+ lim_process_action_vendor_specific(mac, bd,
vendor_specific,
NULL);
break;
@@ -2160,12 +2157,12 @@ void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd)
*/
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,
+ lim_send_sme_mgmt_frame_ind(
+ mac, 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));
+ WMA_GET_RX_CH(bd), NULL,
+ WMA_GET_RX_RSSI_NORMALIZED(bd),
+ RXMGMT_FLAG_NONE);
break;
default:
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 75952720f3b9..5cded988402d 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -717,6 +717,47 @@ static void lim_print_ht_cap(tpAniSirGlobal mac_ctx, tpPESession session,
}
}
+typedef enum wlan_crypto_rsn_cap {
+ WLAN_CRYPTO_RSN_CAP_PREAUTH = 0x01,
+ WLAN_CRYPTO_RSN_CAP_MFP_ENABLED = 0x80,
+ WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED = 0x40,
+} wlan_crypto_rsn_cap;
+
+/**
+ * lim_check_sae_pmf_cap() - check pmf capability for SAE STA
+ * @session: pointer to pe session entry
+ * @rsn: pointer to RSN
+ * @akm_type: AKM type
+ *
+ * This function checks if SAE STA is pmf capable when SAE SAP is pmf
+ * capable. Reject with eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION
+ * if SAE STA is pmf disable.
+ *
+ * Return: tSirMacStatusCodes
+ */
+#ifdef WLAN_FEATURE_SAE
+static tSirMacStatusCodes lim_check_sae_pmf_cap(tpPESession session,
+ tDot11fIERSN *rsn,
+ enum ani_akm_type akm_type)
+{
+ tSirMacStatusCodes status = eSIR_MAC_SUCCESS_STATUS;
+
+ if (session->pLimStartBssReq->pmfCapable &&
+ (rsn->RSN_Cap[0] & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) == 0 &&
+ akm_type == ANI_AKM_TYPE_SAE)
+ status = eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION_STATUS;
+
+ return status;
+}
+#else
+static tSirMacStatusCodes lim_check_sae_pmf_cap(tpPESession session,
+ tDot11fIERSN *rsn,
+ enum ani_akm_type akm_type)
+{
+ return eSIR_MAC_SUCCESS_STATUS;
+}
+#endif
+
/**
* lim_check_wpa_rsn_ie() - wpa and rsn ie related checks
* @session: pointer to pe session entry
@@ -739,6 +780,8 @@ static bool lim_check_wpa_rsn_ie(tpPESession session, tpAniSirGlobal mac_ctx,
tDot11fIEWPA dot11f_ie_wpa = {0};
tDot11fIERSN dot11f_ie_rsn = {0};
tSirRetStatus status = eSIR_SUCCESS;
+ enum ani_akm_type akm_type;
+ tSirMacStatusCodes mac_status;
/*
* Clear the buffers so that frame parser knows that there isn't a
@@ -826,6 +869,20 @@ static bool lim_check_wpa_rsn_ie(tpPESession session, tpAniSirGlobal mac_ctx,
session);
return false;
}
+ akm_type = lim_translate_rsn_oui_to_akm_type(
+ dot11f_ie_rsn.akm_suite[0]);
+
+ mac_status = lim_check_sae_pmf_cap(session, &dot11f_ie_rsn,
+ akm_type);
+ if (eSIR_MAC_SUCCESS_STATUS != mac_status) {
+ /* Reject pmf disable SAE STA */
+ pe_warn("Re/Assoc rejected from: " MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(hdr->sa));
+ lim_send_assoc_rsp_mgmt_frame(mac_ctx, mac_status,
+ 1, hdr->sa, sub_type,
+ 0, session);
+ return false;
+ }
} else if (assoc_req->wpaPresent) {
if (!assoc_req->wpa.length) {
pe_warn("Re/Assoc rejected from: "
@@ -987,6 +1044,8 @@ static bool lim_process_assoc_req_no_sta_ctx(tpAniSirGlobal mac_ctx,
}
/* Delete 'pre-auth' context of STA */
*auth_type = sta_pre_auth_ctx->authType;
+ if (sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE)
+ assoc_req->is_sae_authenticated = true;
lim_delete_pre_auth_node(mac_ctx, hdr->sa);
/* All is well. Assign AID (after else part) */
return true;
@@ -1676,25 +1735,11 @@ static bool lim_update_sta_ctx(tpAniSirGlobal mac_ctx, tpPESession session,
return true;
}
-/**
- * lim_process_assoc_cleanup() - frees up resources used in function
- * lim_process_assoc_req_frame()
- * @mac_ctx: pointer to Global MAC structure
- * @session: pointer to pe session entry
- * @assoc_req: pointer to ASSOC/REASSOC Request frame
- * @sta_ds: station dph entry
- * @tmp_assoc_req: pointer to tmp ASSOC/REASSOC Request frame
- * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above
- *
- * Frees up resources used in function lim_process_assoc_req_frame
- *
- * Return: void
- */
-static void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx,
- tpPESession session,
- tpSirAssocReq assoc_req,
- tpDphHashNode sta_ds,
- bool *assoc_req_copied)
+void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx,
+ tpPESession session,
+ tpSirAssocReq assoc_req,
+ tpDphHashNode sta_ds,
+ bool assoc_req_copied)
{
tpSirAssocReq tmp_assoc_req;
@@ -1707,7 +1752,7 @@ static void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx,
qdf_mem_free(assoc_req);
/* to avoid double free */
- if (*assoc_req_copied && session->parsedAssocReq)
+ if (assoc_req_copied && session->parsedAssocReq)
session->parsedAssocReq[sta_ds->assocId] = NULL;
}
@@ -1732,6 +1777,170 @@ static void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx,
}
/**
+ * lim_defer_sme_indication() - Defer assoc indication to SME
+ * @mac_ctx: Pointer to Global MAC structure
+ * @session: pe session entry
+ * @sub_type: Indicates whether it is Association Request(=0) or Reassociation
+ * Request(=1) frame
+ * @hdr: A pointer to the MAC header
+ * @assoc_req: pointer to ASSOC/REASSOC Request frame
+ * @pmf_connection: flag indicating pmf connection
+ * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above
+ * @dup_entry: flag indicating if duplicate entry found
+ *
+ * Defer Initialization of PE data structures and wait for an external event.
+ * lim_send_assoc_ind_to_sme() will be called to initialize PE data structures
+ * when the expected event is received.
+ *
+ * Return: void
+ */
+static void lim_defer_sme_indication(tpAniSirGlobal mac_ctx,
+ tpPESession session,
+ uint8_t sub_type,
+ tpSirMacMgmtHdr hdr,
+ tpSirAssocReq assoc_req,
+ bool pmf_connection,
+ bool assoc_req_copied,
+ bool dup_entry,
+ struct sDphHashNode *sta_ds)
+{
+ struct tLimPreAuthNode *sta_pre_auth_ctx;
+ /* Extract pre-auth context for the STA, if any. */
+ sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa);
+ sta_pre_auth_ctx->assoc_req.present = true;
+ sta_pre_auth_ctx->assoc_req.sub_type = sub_type;
+ qdf_mem_copy(&sta_pre_auth_ctx->assoc_req.hdr, hdr,
+ sizeof(tSirMacMgmtHdr));
+ sta_pre_auth_ctx->assoc_req.assoc_req = assoc_req;
+ sta_pre_auth_ctx->assoc_req.pmf_connection = pmf_connection;
+ sta_pre_auth_ctx->assoc_req.assoc_req_copied = assoc_req_copied;
+ sta_pre_auth_ctx->assoc_req.dup_entry = dup_entry;
+ sta_pre_auth_ctx->assoc_req.sta_ds = sta_ds;
+}
+
+bool lim_send_assoc_ind_to_sme(tpAniSirGlobal mac_ctx,
+ tpPESession session,
+ uint8_t sub_type,
+ tpSirMacMgmtHdr hdr,
+ tpSirAssocReq assoc_req,
+ bool pmf_connection,
+ bool *assoc_req_copied,
+ bool dup_entry, bool force_1x1)
+{
+ uint16_t peer_idx;
+ struct tLimPreAuthNode *sta_pre_auth_ctx;
+ tpDphHashNode sta_ds = NULL;
+ tHalBitVal qos_mode;
+ tAniAuthType auth_type;
+ uint8_t update_ctx = false;
+
+ limGetQosMode(session, &qos_mode);
+ /* Extract 'associated' context for STA, if any. */
+ sta_ds = dph_lookup_hash_entry(mac_ctx, hdr->sa, &peer_idx,
+ &session->dph.dphHashTable);
+
+ /* Extract pre-auth context for the STA, if any. */
+ sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa);
+
+ if (!sta_ds) {
+ if (!lim_process_assoc_req_no_sta_ctx(mac_ctx, hdr, session,
+ assoc_req, sub_type,
+ sta_pre_auth_ctx, sta_ds,
+ &auth_type))
+ return false;
+ } else {
+ if (!lim_process_assoc_req_sta_ctx(mac_ctx, hdr, session,
+ assoc_req, sub_type,
+ sta_pre_auth_ctx, sta_ds,
+ peer_idx, &auth_type,
+ &update_ctx))
+ return false;
+ goto send_ind_to_sme;
+ }
+
+ /* check if sta is allowed per QoS AC rules */
+ if (!lim_chk_wmm(mac_ctx, hdr, session, assoc_req, sub_type, qos_mode))
+ return false;
+
+ /* STA is Associated ! */
+ pe_debug("Received: %s Req successful from " MAC_ADDRESS_STR,
+ (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(hdr->sa));
+
+ /*
+ * AID for this association will be same as the peer Index used in DPH
+ * table. Assign unused/least recently used peer Index from perStaDs.
+ * NOTE: lim_assign_peer_idx() assigns AID values ranging between
+ * 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT)
+ */
+
+ peer_idx = lim_assign_peer_idx(mac_ctx, session);
+
+ if (!peer_idx) {
+ /* Could not assign AID. Reject association */
+ pe_err("PeerIdx not avaialble. Reject associaton");
+ lim_reject_association(mac_ctx, hdr->sa, sub_type,
+ true, auth_type, peer_idx, false,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ session);
+ return false;
+ }
+
+ /* Add an entry to hash table maintained by DPH module */
+
+ sta_ds = dph_add_hash_entry(mac_ctx, hdr->sa, peer_idx,
+ &session->dph.dphHashTable);
+
+ if (!sta_ds) {
+ /* Could not add hash table entry at DPH */
+ pe_err("couldn't add hash entry at DPH for aid: %d MacAddr:"
+ MAC_ADDRESS_STR, peer_idx, MAC_ADDR_ARRAY(hdr->sa));
+
+ /* Release AID */
+ lim_release_peer_idx(mac_ctx, peer_idx, session);
+
+ lim_reject_association(mac_ctx, hdr->sa, sub_type,
+ true, auth_type, peer_idx, false,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ session);
+ return false;
+ }
+
+send_ind_to_sme:
+ if (!lim_update_sta_ds(mac_ctx, hdr, session, assoc_req,
+ sub_type, sta_ds, auth_type,
+ assoc_req_copied, peer_idx, qos_mode,
+ pmf_connection, force_1x1))
+ return false;
+
+ /* BTAMP: Storing the parsed assoc request in the session array */
+ if (session->parsedAssocReq)
+ session->parsedAssocReq[sta_ds->assocId] = assoc_req;
+ *assoc_req_copied = true;
+
+ /* If it is duplicate entry wait till the peer is deleted */
+ if (!dup_entry) {
+ if (!lim_update_sta_ctx(mac_ctx, session, assoc_req,
+ sub_type, sta_ds, update_ctx))
+ return false;
+ }
+
+ /* AddSta is success here */
+ if (LIM_IS_AP_ROLE(session) && IS_DOT11_MODE_HT(session->dot11mode) &&
+ assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) {
+ /*
+ * Update in the HAL Sta Table for the Update of the Protection
+ * Mode
+ */
+ lim_post_sm_state_update(mac_ctx, sta_ds->staIndex,
+ sta_ds->htMIMOPSState, sta_ds->staAddr,
+ session->smeSessionId);
+ }
+
+ return true;
+}
+
+/**
* lim_process_assoc_req_frame() - Process RE/ASSOC Request frame.
* @mac_ctx: Pointer to Global MAC structure
* @rx_pkt_info: A pointer to Buffer descriptor + associated PDUs
@@ -1747,14 +1956,13 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
uint8_t sub_type, tpPESession session)
{
bool pmf_connection = false, assoc_req_copied = false;
- uint8_t update_ctx, *frm_body;
- uint16_t peer_idx, assoc_id = 0;
+ uint8_t *frm_body;
+ uint16_t assoc_id = 0;
uint32_t frame_len;
uint32_t phy_mode;
tHalBitVal qos_mode;
tpSirMacMgmtHdr hdr;
struct tLimPreAuthNode *sta_pre_auth_ctx;
- tAniAuthType auth_type;
tSirMacCapabilityInfo local_cap;
tpDphHashNode sta_ds = NULL;
tpSirAssocReq assoc_req;
@@ -1917,8 +2125,6 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
sub_type, &local_cap))
goto error;
- update_ctx = false;
-
if (false == lim_chk_ssid(mac_ctx, hdr, session, assoc_req, sub_type))
goto error;
@@ -1958,36 +2164,6 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
assoc_req, sub_type, &pmf_connection))
goto error;
- /* Extract 'associated' context for STA, if any. */
- sta_ds = dph_lookup_hash_entry(mac_ctx, hdr->sa, &peer_idx,
- &session->dph.dphHashTable);
-
- /* Extract pre-auth context for the STA, if any. */
- sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa);
-
- if (sta_ds == NULL) {
- if (false == lim_process_assoc_req_no_sta_ctx(mac_ctx, hdr,
- session, assoc_req, sub_type, sta_pre_auth_ctx,
- sta_ds, &auth_type))
- goto error;
- } else {
- if (false == lim_process_assoc_req_sta_ctx(mac_ctx, hdr,
- session, assoc_req, sub_type, sta_pre_auth_ctx,
- sta_ds, peer_idx, &auth_type, &update_ctx))
- goto error;
- goto sendIndToSme;
- }
-
- /* check if sta is allowed per QoS AC rules */
- if (false == lim_chk_wmm(mac_ctx, hdr, session,
- assoc_req, sub_type, qos_mode))
- goto error;
-
- /* STA is Associated ! */
- pe_err("Received: %s Req successful from " MAC_ADDRESS_STR,
- (LIM_ASSOC == sub_type) ? "Assoc" : "ReAssoc",
- MAC_ADDR_ARRAY(hdr->sa));
-
if (session->pePersona == QDF_P2P_GO_MODE) {
/*
* WAR: In P2P GO mode, if the P2P client device
@@ -2007,82 +2183,38 @@ void lim_process_assoc_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
frame_len - LIM_ASSOC_REQ_IE_OFFSET);
}
- /*
- * AID for this association will be same as the peer Index used in DPH
- * table. Assign unused/least recently used peer Index from perStaDs.
- * NOTE: lim_assign_peer_idx() assigns AID values ranging between
- * 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT)
- */
-
- peer_idx = lim_assign_peer_idx(mac_ctx, session);
-
- if (!peer_idx) {
- /* Could not assign AID. Reject association */
- pe_err("PeerIdx not avaialble. Reject associaton");
- lim_reject_association(mac_ctx, hdr->sa, sub_type,
- true, auth_type, peer_idx, false,
- eSIR_MAC_UNSPEC_FAILURE_STATUS,
- session);
- goto error;
- }
-
- /* Add an entry to hash table maintained by DPH module */
-
- sta_ds = dph_add_hash_entry(mac_ctx, hdr->sa, peer_idx,
- &session->dph.dphHashTable);
-
- if (sta_ds == NULL) {
- /* Could not add hash table entry at DPH */
- pe_err("couldn't add hash entry at DPH for aid: %d MacAddr:"
- MAC_ADDRESS_STR, peer_idx, MAC_ADDR_ARRAY(hdr->sa));
-
- /* Release AID */
- lim_release_peer_idx(mac_ctx, peer_idx, session);
+ /* Extract pre-auth context for the STA, if any. */
+ sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx, hdr->sa);
- lim_reject_association(mac_ctx, hdr->sa, sub_type,
- true, auth_type, peer_idx, false,
- eSIR_MAC_UNSPEC_FAILURE_STATUS,
- session);
- goto error;
+ /* SAE authentication is offloaded to hostapd. Hostapd sends
+ * authentication status to driver after completing SAE
+ * authentication (after sending out 4/4 SAE auth frame).
+ * There is a possible race condition where driver gets
+ * assoc request from SAE station before getting authentication
+ * status from hostapd. Don't reject the association in such
+ * cases and defer the processing of assoc request frame by caching
+ * the frame and process it when the auth status is received.
+ */
+ if (sta_pre_auth_ctx &&
+ sta_pre_auth_ctx->authType == eSIR_AUTH_TYPE_SAE &&
+ sta_pre_auth_ctx->mlmState == eLIM_MLM_WT_SAE_AUTH_STATE) {
+ pe_debug("Received assoc request frame while SAE authentication is in progress; Defer association request handling till SAE auth status is received");
+ lim_defer_sme_indication(mac_ctx, session, sub_type, hdr,
+ assoc_req, pmf_connection,
+ assoc_req_copied, dup_entry, sta_ds);
+ return;
}
-sendIndToSme:
- if (false == lim_update_sta_ds(mac_ctx, hdr, session, assoc_req,
- sub_type, sta_ds, auth_type,
- &assoc_req_copied, peer_idx, qos_mode,
- pmf_connection, force_1x1))
+ /* Send assoc indication to SME */
+ if (!lim_send_assoc_ind_to_sme(mac_ctx, session, sub_type, hdr,
+ assoc_req, pmf_connection,
+ &assoc_req_copied, dup_entry, force_1x1))
goto error;
-
- /* BTAMP: Storing the parsed assoc request in the session array */
- if (session->parsedAssocReq)
- session->parsedAssocReq[sta_ds->assocId] = assoc_req;
- assoc_req_copied = true;
-
- /* If it is duplicate entry wait till the peer is deleted */
- if (dup_entry != true) {
- if (false == lim_update_sta_ctx(mac_ctx, session, assoc_req,
- sub_type, sta_ds, update_ctx))
- goto error;
- }
-
- /* AddSta is sucess here */
- if (LIM_IS_AP_ROLE(session) && IS_DOT11_MODE_HT(session->dot11mode) &&
- assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) {
- /*
- * Update in the HAL Sta Table for the Update of the Protection
- * Mode
- */
- lim_post_sm_state_update(mac_ctx, sta_ds->staIndex,
- sta_ds->htMIMOPSState, sta_ds->staAddr,
- session->smeSessionId);
- }
-
return;
-
error:
lim_process_assoc_cleanup(mac_ctx, session, assoc_req, sta_ds,
- &assoc_req_copied);
+ assoc_req_copied);
return;
}
@@ -2510,6 +2642,8 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx,
sizeof(tDot11fIEVHTCaps));
lim_fill_assoc_ind_vht_info(mac_ctx, session_entry, assoc_req,
assoc_ind, sta_ds);
+ assoc_ind->is_sae_authenticated =
+ assoc_req->is_sae_authenticated;
lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND,
(uint32_t *) assoc_ind);
qdf_mem_free(assoc_ind);
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 8948bda446af..f1048e714c47 100644
--- a/core/mac/src/pe/lim/lim_process_auth_frame.c
+++ b/core/mac/src/pe/lim/lim_process_auth_frame.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -44,6 +44,31 @@
#include "lim_process_fils.h"
#include "lim_send_messages.h"
+#ifdef WLAN_FEATURE_SAE
+/**
+ * sap_sae_enabled() - API to check if SAP SAE availability.
+ * @mac_ctx: pointer to MAC context
+ *
+ * This API reads the SAE setting from MAC/WNI layer.
+ *
+ * Return: true if SAE is enabled, false otherwise.
+ */
+static inline bool sap_sae_enabled(tpAniSirGlobal mac_ctx)
+{
+ uint32_t sap_sae_enabled;
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_SAP_SAE_ENABLED,
+ &sap_sae_enabled) != eSIR_SUCCESS) {
+ sap_sae_enabled = 0;
+ }
+ return (sap_sae_enabled != 0);
+}
+#else
+static inline bool sap_sae_enabled(tpAniSirGlobal mac_ctx)
+{
+ return false;
+}
+#endif
+
/**
* is_auth_valid
*
@@ -278,7 +303,44 @@ static void lim_process_auth_open_system_algo(tpAniSirGlobal mac_ctx,
#ifdef WLAN_FEATURE_SAE
/**
- * lim_process_sae_auth_frame()-Process SAE authentication frame
+ * lim_external_auth_add_pre_auth_node() - Add preauth node for the peer
+ * performing external authentication
+ * @mac_ctx: MAC context
+ * @mac_hdr: Mac header of the packet
+ * @mlm_state: MLM state to be marked to track SAE authentication
+ *
+ * Return: None
+ */
+static void lim_external_auth_add_pre_auth_node(tpAniSirGlobal mac_ctx,
+ tpSirMacMgmtHdr mac_hdr,
+ tLimMlmStates mlm_state)
+{
+ struct tLimPreAuthNode *auth_node;
+ tpLimPreAuthTable preauth_table = &mac_ctx->lim.gLimPreAuthTimerTable;
+
+ pe_debug("=======> eSIR_AUTH_TYPE_SAE");
+ /* Create entry for this STA in pre-auth list */
+ auth_node = lim_acquire_free_pre_auth_node(mac_ctx, preauth_table);
+ if (!auth_node) {
+ pe_debug("Max pre-auth nodes reached " MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(mac_hdr->sa));
+ return;
+ }
+ pe_debug("Creating preauth node for SAE peer " MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(mac_hdr->sa));
+ qdf_mem_copy((uint8_t *)auth_node->peerMacAddr,
+ mac_hdr->sa, sizeof(tSirMacAddr));
+ auth_node->mlmState = mlm_state;
+ auth_node->authType = eSIR_AUTH_TYPE_SAE;
+ auth_node->timestamp = qdf_mc_timer_get_system_ticks();
+ auth_node->seq_num = ((mac_hdr->seqControl.seqNumHi << 4) |
+ (mac_hdr->seqControl.seqNumLo));
+ auth_node->assoc_req.present = false;
+ lim_add_pre_auth_node(mac_ctx, auth_node);
+}
+
+/**
+ * lim_process_sae_auth_frame() - Process SAE authentication frame
* @mac_ctx: MAC context
* @rx_pkt_info: Rx packet
* @pe_session: PE session
@@ -286,11 +348,13 @@ static void lim_process_auth_open_system_algo(tpAniSirGlobal mac_ctx,
* Return: None
*/
static void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx,
- uint8_t *rx_pkt_info, tpPESession pe_session)
+ uint8_t *rx_pkt_info,
+ tpPESession pe_session)
{
tpSirMacMgmtHdr mac_hdr;
uint32_t frame_len;
uint8_t *body_ptr;
+ enum rxmgmt_flags rx_flags = RXMGMT_FLAG_NONE;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
@@ -299,19 +363,44 @@ static void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx,
pe_debug("Received SAE Auth frame type %d subtype %d",
mac_hdr->fc.type, mac_hdr->fc.subType);
- if (pe_session->limMlmState != eLIM_MLM_WT_SAE_AUTH_STATE)
- pe_err("received SAE auth response in unexpected state %x",
- pe_session->limMlmState);
+ if (LIM_IS_STA_ROLE(pe_session) &&
+ pe_session->limMlmState != eLIM_MLM_WT_SAE_AUTH_STATE)
+ pe_err("received SAE auth response for STA in unexpected state %x",
+ pe_session->limMlmState);
+
+ if (LIM_IS_AP_ROLE(pe_session)) {
+ struct tLimPreAuthNode *sta_pre_auth_ctx;
+
+ rx_flags = RXMGMT_FLAG_EXTERNAL_AUTH;
+ /* Add preauth node when the first SAE authentication frame
+ * is received and mark state as authenticating.
+ * It's not good to track SAE authentication frames with
+ * authTransactionSeqNumber as it's subjected to
+ * SAE protocol optimizations.
+ */
+ /* Extract pre-auth context for the STA, if any. */
+ sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx,
+ mac_hdr->sa);
+ if (!sta_pre_auth_ctx ||
+ (sta_pre_auth_ctx->mlmState != eLIM_MLM_WT_SAE_AUTH_STATE &&
+ sta_pre_auth_ctx->mlmState !=
+ eLIM_MLM_AUTHENTICATED_STATE)) {
+ lim_external_auth_add_pre_auth_node(
+ mac_ctx, mac_hdr, eLIM_MLM_WT_SAE_AUTH_STATE);
+ }
+ }
lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
- (uint8_t *) mac_hdr,
- frame_len + sizeof(tSirMacMgmtHdr), 0,
- WMA_GET_RX_CH(rx_pkt_info), pe_session,
- WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info));
+ (uint8_t *)mac_hdr,
+ frame_len + sizeof(tSirMacMgmtHdr), 0,
+ WMA_GET_RX_CH(rx_pkt_info), pe_session,
+ WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
+ rx_flags);
}
#else
-static inline void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx,
- uint8_t *rx_pkt_info, tpPESession pe_session)
+static inline void lim_process_sae_auth_frame(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info,
+ tpPESession pe_session)
{}
#endif
@@ -1417,10 +1506,11 @@ lim_process_auth_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
pe_err("failed to convert Auth Frame to structure or Auth is not valid");
goto free;
}
- } else if ((auth_alg ==
- eSIR_AUTH_TYPE_SAE) && (LIM_IS_STA_ROLE(pe_session))) {
- lim_process_sae_auth_frame(mac_ctx,
- rx_pkt_info, pe_session);
+ } else if (auth_alg == eSIR_AUTH_TYPE_SAE) {
+ if (sap_sae_enabled(mac_ctx) &&
+ (LIM_IS_STA_ROLE(pe_session) || LIM_IS_AP_ROLE(pe_session)))
+ lim_process_sae_auth_frame(mac_ctx, rx_pkt_info,
+ pe_session);
goto free;
} else if ((sir_convert_auth_frame2_struct(mac_ctx, body_ptr,
frame_len, rx_auth_frame) != eSIR_SUCCESS)
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index c6c3e8b3bd88..7d0df1cd9a88 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -64,6 +64,116 @@ static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx,
#ifdef WLAN_FEATURE_SAE
/**
+ * lim_process_sae_msg_sta() - Process SAE message for STA
+ * @mac: Global MAC pointer
+ * @session: Pointer to the PE session entry
+ * @sae_msg: SAE message buffer pointer
+ *
+ * Return: None
+ */
+static void lim_process_sae_msg_sta(tpAniSirGlobal mac,
+ tpPESession session,
+ struct sir_sae_msg *sae_msg)
+{
+ switch (session->limMlmState) {
+ case eLIM_MLM_WT_SAE_AUTH_STATE:
+ /* SAE authentication is completed.
+ * Restore from auth state
+ */
+ if (tx_timer_running(&mac->lim.limTimers.sae_auth_timer))
+ lim_deactivate_and_change_timer(mac,
+ eLIM_AUTH_SAE_TIMER);
+ /* success */
+ if (sae_msg->sae_status == IEEE80211_STATUS_SUCCESS)
+ lim_restore_from_auth_state(mac,
+ eSIR_SME_SUCCESS,
+ eSIR_MAC_SUCCESS_STATUS,
+ session);
+ else
+ lim_restore_from_auth_state(
+ mac, eSIR_SME_AUTH_REFUSED,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS, session);
+ break;
+ default:
+ /* SAE msg is received in unexpected state */
+ pe_err("received SAE msg instate %X", session->limMlmState);
+ lim_print_mlm_state(mac, LOGE, session->limMlmState);
+ break;
+ }
+}
+
+/**
+ * lim_process_sae_msg_ap() - Process SAE message
+ * @mac: Global MAC pointer
+ * @session: Pointer to the PE session entry
+ * @sae_msg: SAE message buffer pointer
+ *
+ * Return: None
+ */
+static void lim_process_sae_msg_ap(tpAniSirGlobal mac,
+ tpPESession session,
+ struct sir_sae_msg *sae_msg)
+{
+ struct tLimPreAuthNode *sta_pre_auth_ctx;
+ struct lim_assoc_data *assoc_req;
+ /* Extract pre-auth context for the STA and move limMlmState
+ * of preauth node to eLIM_MLM_AUTHENTICATED_STATE
+ */
+ sta_pre_auth_ctx = lim_search_pre_auth_list(mac,
+ sae_msg->peer_mac_addr);
+
+ if (!sta_pre_auth_ctx) {
+ pe_debug("No preauth node created for "
+ MAC_ADDRESS_STR,
+ MAC_ADDR_ARRAY(sae_msg->peer_mac_addr));
+ return;
+ }
+
+ assoc_req = &sta_pre_auth_ctx->assoc_req;
+
+ if (sae_msg->sae_status != IEEE80211_STATUS_SUCCESS) {
+ pe_debug("SAE authentication failed for "
+ MAC_ADDRESS_STR " status: %u",
+ MAC_ADDR_ARRAY(sae_msg->peer_mac_addr),
+ sae_msg->sae_status);
+ if (assoc_req->present) {
+ pe_debug("Assoc req cached; clean it up");
+ lim_process_assoc_cleanup(mac, session,
+ assoc_req->assoc_req,
+ assoc_req->sta_ds,
+ assoc_req->assoc_req_copied);
+ assoc_req->present = false;
+ }
+ lim_delete_pre_auth_node(mac, sae_msg->peer_mac_addr);
+ return;
+ }
+ sta_pre_auth_ctx->mlmState = eLIM_MLM_AUTHENTICATED_STATE;
+ /* Send assoc indication to SME if any assoc request is cached*/
+ if (assoc_req->present) {
+ /* Assoc request is present in preauth context. Get the assoc
+ * request and make it invalid in preauth context. It'll be
+ * freed later in the legacy path.
+ */
+ bool assoc_req_copied;
+
+ assoc_req->present = false;
+ pe_debug("Assoc req cached; handle it");
+ if (lim_send_assoc_ind_to_sme(mac, session,
+ assoc_req->sub_type,
+ &assoc_req->hdr,
+ assoc_req->assoc_req,
+ assoc_req->pmf_connection,
+ &assoc_req_copied,
+ assoc_req->dup_entry,
+ false) == false)
+ lim_process_assoc_cleanup(mac, session,
+ assoc_req->assoc_req,
+ assoc_req->sta_ds,
+ assoc_req_copied);
+ }
+}
+
+/**
* lim_process_sae_msg() - Process SAE message
* @mac: Global MAC pointer
* @body: Buffer pointer
@@ -87,40 +197,23 @@ static void lim_process_sae_msg(tpAniSirGlobal mac, struct sir_sae_msg *body)
return;
}
- if (session->pePersona != QDF_STA_MODE) {
+ if (session->pePersona != QDF_STA_MODE &&
+ session->pePersona != QDF_SAP_MODE) {
pe_err("SAE:Not supported in this mode %d",
session->pePersona);
return;
}
- pe_debug("SAE:status %d limMlmState %d pePersona %d",
- sae_msg->sae_status, session->limMlmState,
- session->pePersona);
- switch (session->limMlmState) {
- case eLIM_MLM_WT_SAE_AUTH_STATE:
- /* SAE authentication is completed. Restore from auth state */
- if (tx_timer_running(&mac->lim.limTimers.sae_auth_timer))
- lim_deactivate_and_change_timer(mac,
- eLIM_AUTH_SAE_TIMER);
- /* success */
- if (sae_msg->sae_status == IEEE80211_STATUS_SUCCESS)
- lim_restore_from_auth_state(mac,
- eSIR_SME_SUCCESS,
- eSIR_MAC_SUCCESS_STATUS,
- session);
- else
- lim_restore_from_auth_state(mac,
- eSIR_SME_AUTH_REFUSED,
- eSIR_MAC_UNSPEC_FAILURE_STATUS,
- session);
- break;
- default:
- /* SAE msg is received in unexpected state */
- pe_err("received SAE msg in state %X",
- session->limMlmState);
- lim_print_mlm_state(mac, LOGE, session->limMlmState);
- break;
- }
+ pe_debug("SAE:status %d limMlmState %d pePersona %d peer: "
+ MAC_ADDRESS_STR, sae_msg->sae_status,
+ session->limMlmState, session->pePersona,
+ MAC_ADDR_ARRAY(sae_msg->peer_mac_addr));
+ if (LIM_IS_STA_ROLE(session))
+ lim_process_sae_msg_sta(mac, session, sae_msg);
+ else if (LIM_IS_AP_ROLE(session))
+ lim_process_sae_msg_ap(mac, session, sae_msg);
+ else
+ pe_debug("SAE message on unsupported interface");
}
#else
static inline void lim_process_sae_msg(tpAniSirGlobal mac, void *body)
@@ -907,12 +1000,13 @@ lim_check_mgmt_registered_frames(tpAniSirGlobal mac_ctx, uint8_t *buff_desc,
QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
FL("rcvd frame match with registered frame params"));
/* Indicate this to SME */
- lim_send_sme_mgmt_frame_ind(mac_ctx, hdr->fc.subType,
- (uint8_t *) hdr,
+ lim_send_sme_mgmt_frame_ind(
+ mac_ctx, hdr->fc.subType, (uint8_t *)hdr,
WMA_GET_RX_PAYLOAD_LEN(buff_desc) +
- sizeof(tSirMacMgmtHdr), mgmt_frame->sessionId,
- WMA_GET_RX_CH(buff_desc), session_entry,
- WMA_GET_RX_RSSI_NORMALIZED(buff_desc));
+ sizeof(tSirMacMgmtHdr),
+ mgmt_frame->sessionId, WMA_GET_RX_CH(buff_desc),
+ session_entry, WMA_GET_RX_RSSI_NORMALIZED(buff_desc),
+ RXMGMT_FLAG_NONE);
if ((type == SIR_MAC_MGMT_FRAME)
&& (fc.type == SIR_MAC_MGMT_FRAME)
diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
index 5110ecd9432a..f21787407d6b 100644
--- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
+++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -757,7 +757,7 @@ lim_fill_assoc_ind_params(tpAniSirGlobal mac_ctx,
if (assoc_ind->VHTCaps.present)
sme_assoc_ind->VHTCaps = assoc_ind->VHTCaps;
sme_assoc_ind->capability_info = assoc_ind->capabilityInfo;
-
+ sme_assoc_ind->is_sae_authenticated = assoc_ind->is_sae_authenticated;
}
/**
diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c
index 82961f0b025c..af06148a3793 100644
--- a/core/mac/src/pe/lim/lim_process_probe_req_frame.c
+++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -555,7 +555,8 @@ lim_indicate_probe_req_to_hdd(tpAniSirGlobal pMac, uint8_t *pBd,
(frameLen + sizeof(tSirMacMgmtHdr)),
psessionEntry->smeSessionId, WMA_GET_RX_CH(pBd),
psessionEntry,
- WMA_GET_RX_RSSI_NORMALIZED(pBd));
+ WMA_GET_RX_RSSI_NORMALIZED(pBd),
+ RXMGMT_FLAG_NONE);
} /*** end lim_indicate_probe_req_to_hdd() ***/
/**
diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
index e5e33917fb9c..a6b3ce7807d6 100644
--- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c
+++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -3602,21 +3602,33 @@ void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type,
session_entry);
goto end;
} else {
+ uint8_t add_pre_auth_context = true;
/*
* SME_ASSOC_CNF status is non-success, so STA is not allowed
* to be associated since the HAL sta entry is created for
* denied STA we need to remove this HAL entry.
* So to do that set updateContext to 1
*/
+ tSirMacStatusCodes mac_status_code =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
if (!sta_ds->mlmStaContext.updateContext)
sta_ds->mlmStaContext.updateContext = 1;
- pe_debug("Recv Assoc Cnf, status Code : %d(assoc id=%d)",
- assoc_cnf.statusCode, sta_ds->assocId);
+ pe_debug("Recv Assoc Cnf, status Code : %d(assoc id=%d) Reason code: %d",
+ assoc_cnf.statusCode, sta_ds->assocId,
+ assoc_cnf.mac_status_code);
+ if (assoc_cnf.mac_status_code)
+ mac_status_code = assoc_cnf.mac_status_code;
+ if (assoc_cnf.mac_status_code == eSIR_MAC_INVALID_PMKID ||
+ assoc_cnf.mac_status_code ==
+ eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS)
+ add_pre_auth_context = false;
+
lim_reject_association(mac_ctx, sta_ds->staAddr,
sta_ds->mlmStaContext.subType,
- true, sta_ds->mlmStaContext.authType,
+ add_pre_auth_context,
+ sta_ds->mlmStaContext.authType,
sta_ds->assocId, true,
- eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ mac_status_code,
session_entry);
}
end:
diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c
index 5cf1f04803e0..b4831eef1f2f 100644
--- a/core/mac/src/pe/lim/lim_process_tdls.c
+++ b/core/mac/src/pe/lim/lim_process_tdls.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -2223,8 +2223,7 @@ lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads,
tDot11fIEVHTCaps *vht_caps)
{
tSirMacRateSet temp_rate_set;
- uint32_t i, j, val, min, is_a_rate;
- tSirMacRateSet temp_rate_set2;
+ uint32_t i, j, val, is_a_rate;
uint32_t phymode;
uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET];
tpSirSupportedRates rates;
@@ -2233,70 +2232,9 @@ lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads,
uint8_t nss;
is_a_rate = 0;
- temp_rate_set2.numRates = 0;
lim_get_phy_mode(mac_ctx, &phymode, NULL);
- /* get own rate set */
- val = WNI_CFG_OPERATIONAL_RATE_SET_LEN;
- if (wlan_cfg_get_str(mac_ctx, WNI_CFG_OPERATIONAL_RATE_SET,
- (uint8_t *) &temp_rate_set.rate,
- &val) != eSIR_SUCCESS) {
- /* Could not get rateset from CFG. Log error. */
- pe_err("could not retrieve rateset");
- val = 0;
- }
- temp_rate_set.numRates = val;
-
- if (phymode == WNI_CFG_PHY_MODE_11G) {
- /* get own extended rate set */
- val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN;
- if (wlan_cfg_get_str(mac_ctx,
- WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
- (uint8_t *) &temp_rate_set2.rate,
- &val) != eSIR_SUCCESS)
- temp_rate_set2.numRates = val;
- }
-
- if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) {
- pe_err("more than 12 rates in CFG");
- return eSIR_FAILURE;
- }
-
- /**
- * Handling of the rate set IEs is the following:
- * - keep only rates that we support and that the station supports
- * - sort and the rates into the pSta->rate array
- */
-
- /* Copy all rates in temp_rate_set, there are 12 rates max */
- for (i = 0; i < temp_rate_set2.numRates; i++)
- temp_rate_set.rate[i + temp_rate_set.numRates] =
- temp_rate_set2.rate[i];
-
- temp_rate_set.numRates += temp_rate_set2.numRates;
-
- /**
- * Sort rates in temp_rate_set (they are likely to be already sorted)
- * put the result in temp_rate_set2
- */
- temp_rate_set2.numRates = 0;
-
- for (i = 0; i < temp_rate_set.numRates; i++) {
- min = 0;
- val = 0xff;
-
- for (j = 0; j < temp_rate_set.numRates; j++)
- if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) {
- val = temp_rate_set.rate[j] & 0x7f;
- min = j;
- }
-
- temp_rate_set2.rate[temp_rate_set2.numRates++] =
- temp_rate_set.rate[min];
- temp_rate_set.rate[min] = 0xff;
- }
-
/**
* Copy received rates in temp_rate_set, the parser has ensured
* unicity of the rates so there cannot be more than 12 .
@@ -2315,27 +2253,22 @@ lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads,
rates = &stads->supportedRates;
qdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0);
- for (i = 0; i < temp_rate_set2.numRates; i++) {
- for (j = 0; j < temp_rate_set.numRates; j++) {
- if ((temp_rate_set2.rate[i] & 0x7F) !=
- (temp_rate_set.rate[j] & 0x7F))
- continue;
-
- if ((b_rateindex > SIR_NUM_11B_RATES) ||
- (a_rateindex > SIR_NUM_11A_RATES)) {
- pe_warn("Invalid number of rates (11b->%d, 11a->%d)",
- b_rateindex, a_rateindex);
- return eSIR_FAILURE;
- }
- if (sirIsArate(temp_rate_set2.rate[i] & 0x7f)) {
- is_a_rate = 1;
- if (a_rateindex < SIR_NUM_11A_RATES)
- rates->llaRates[a_rateindex++] = temp_rate_set2.rate[i];
- } else {
- if (b_rateindex < SIR_NUM_11B_RATES)
- rates->llbRates[b_rateindex++] = temp_rate_set2.rate[i];
- }
- break;
+ for (j = 0; j < temp_rate_set.numRates; j++) {
+ if ((b_rateindex > SIR_NUM_11B_RATES) ||
+ (a_rateindex > SIR_NUM_11A_RATES)) {
+ pe_warn("Invalid number of rates (11b->%d, 11a->%d)",
+ b_rateindex, a_rateindex);
+ return eSIR_FAILURE;
+ }
+ if (sirIsArate(temp_rate_set.rate[j] & 0x7f)) {
+ is_a_rate = 1;
+ if (a_rateindex < SIR_NUM_11A_RATES)
+ rates->llaRates[a_rateindex++] =
+ temp_rate_set.rate[j];
+ } else {
+ if (b_rateindex < SIR_NUM_11B_RATES)
+ rates->llbRates[b_rateindex++] =
+ temp_rate_set.rate[j];
}
}
diff --git a/core/mac/src/pe/lim/lim_security_utils.c b/core/mac/src/pe/lim/lim_security_utils.c
index a99bcff2a561..f6c544102f83 100644
--- a/core/mac/src/pe/lim/lim_security_utils.c
+++ b/core/mac/src/pe/lim/lim_security_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -320,9 +320,18 @@ void lim_add_pre_auth_node(tpAniSirGlobal pMac, struct tLimPreAuthNode *pAuthNod
void lim_release_pre_auth_node(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode)
{
pAuthNode->fFree = 1;
- MTRACE(mac_trace
- (pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION,
- eLIM_PRE_AUTH_CLEANUP_TIMER));
+ if (pAuthNode->authType == eSIR_AUTH_TYPE_SAE &&
+ pAuthNode->assoc_req.present) {
+ tpSirAssocReq assoc =
+ (tpSirAssocReq)pAuthNode->assoc_req.assoc_req;
+
+ if (assoc->assocReqFrameLength)
+ qdf_mem_free(assoc->assocReqFrame);
+ qdf_mem_free(assoc);
+ pAuthNode->assoc_req.present = false;
+ }
+ MTRACE(mac_trace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION,
+ eLIM_PRE_AUTH_CLEANUP_TIMER));
tx_timer_deactivate(&pAuthNode->timer);
pMac->lim.gLimNumPreAuthContexts--;
} /*** end lim_release_pre_auth_node() ***/
diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c
index 87b5598c03de..7d49ff37421d 100644
--- a/core/mac/src/pe/lim/lim_send_management_frames.c
+++ b/core/mac/src/pe/lim/lim_send_management_frames.c
@@ -1629,6 +1629,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
void *packet;
QDF_STATUS qdf_status;
uint16_t add_ie_len, assoc_ack_status;
+ uint16_t current_len = 0, vendor_ie_len = 0;
uint8_t *add_ie;
uint8_t *wps_ie = NULL;
uint8_t power_caps = false;
@@ -1645,7 +1646,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
uint32_t bcn_ie_len = 0;
uint32_t aes_block_size_len = 0;
enum rateid min_rid = RATEID_DEFAULT;
- uint8_t *mbo_ie = NULL;
+ uint8_t *mbo_ie = NULL, *vendor_ies = NULL;
uint8_t mbo_ie_len = 0;
if (NULL == pe_session) {
@@ -1962,6 +1963,33 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
}
/*
+ * Strip rest of the vendor IEs and append to the assoc request frame.
+ * Append the IEs just before MBO IEs as MBO IEs have to be at the
+ * end of the frame.
+ */
+ if (wlan_cfg_get_ie_ptr(add_ie, add_ie_len, SIR_MAC_EID_VENDOR,
+ ONE_BYTE)) {
+ vendor_ies = qdf_mem_malloc(MAX_VENDOR_IES_LEN + 2);
+ if (vendor_ies) {
+ current_len = add_ie_len;
+ sir_status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len,
+ SIR_MAC_EID_VENDOR, ONE_BYTE,
+ NULL,
+ 0,
+ vendor_ies,
+ MAX_VENDOR_IES_LEN);
+ if (sir_status != eSIR_SUCCESS) {
+ pe_err("Failed to strip Vendor IEs");
+ goto end;
+ }
+
+ vendor_ie_len = current_len - add_ie_len;
+ pe_debug("Stripped vendor IEs of size: %u",
+ current_len);
+ }
+ }
+
+ /*
* Do unpack to populate the add_ie buffer to frm structure
* before packing the frm structure. In this way, the IE ordering
* which the latest 802.11 spec mandates is maintained.
@@ -1987,7 +2015,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
}
bytes = payload + sizeof(tSirMacMgmtHdr) +
- aes_block_size_len + mbo_ie_len;
+ aes_block_size_len + mbo_ie_len + vendor_ie_len;
qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
(void **)&packet);
@@ -2027,6 +2055,11 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
pe_warn("Assoc request pack warning (0x%08x)", status);
}
+ /* Copy the vendor IEs to the end of the frame */
+ qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
+ vendor_ies, vendor_ie_len);
+ payload = payload + vendor_ie_len;
+
/* Copy the MBO IE to the end of the frame */
qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
mbo_ie, mbo_ie_len);
@@ -2104,6 +2137,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
goto end;
}
end:
+ qdf_mem_free(vendor_ies);
qdf_mem_free(mbo_ie);
/* Free up buffer allocated for mlm_assoc_req */
qdf_mem_free(mlm_assoc_req);
@@ -4699,12 +4733,16 @@ void lim_send_mgmt_frame_tx(tpAniSirGlobal mac_ctx,
QDF_STATUS qdf_status;
uint8_t *frame;
void *packet;
+ tpSirMacMgmtHdr mac_hdr;
msg_len = mb_msg->msg_len - sizeof(*mb_msg);
pe_debug("sending fc->type: %d fc->subType: %d",
fc->type, fc->subType);
sme_session_id = mb_msg->session_id;
+ mac_hdr = (tpSirMacMgmtHdr)mb_msg->data;
+
+ lim_add_mgmt_seq_num(mac_ctx, mac_hdr);
qdf_status = cds_packet_alloc((uint16_t) msg_len, (void **)&frame,
(void **)&packet);
diff --git a/core/mac/src/pe/lim/lim_send_messages.h b/core/mac/src/pe/lim/lim_send_messages.h
index fd1e661d55d8..b2acad9de49c 100644
--- a/core/mac/src/pe/lim/lim_send_messages.h
+++ b/core/mac/src/pe/lim/lim_send_messages.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2016 2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -88,6 +88,8 @@ void lim_set_active_edca_params(tpAniSirGlobal pMac,
tSirRetStatus lim_send_beacon_filter_info(tpAniSirGlobal pMac,
tpPESession psessionEntry);
+#define MAX_VENDOR_IES_LEN 1532
+
#ifdef WLAN_FEATURE_11W
tSirRetStatus lim_send_exclude_unencrypt_ind(tpAniSirGlobal pMac,
bool excludeUnenc,
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index 8caf092c4af5..babb7ffae70f 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -270,6 +270,7 @@ typedef struct sLimMlmAssocInd {
tDot11fIEHTCaps HTCaps;
tDot11fIEVHTCaps VHTCaps;
+ bool is_sae_authenticated;
} tLimMlmAssocInd, *tpLimMlmAssocInd;
typedef struct sLimMlmReassocReq {
@@ -904,11 +905,23 @@ void
lim_change_channel_with_callback(tpAniSirGlobal pMac, uint8_t newChannel,
CHANGE_CHANNEL_CALLBACK callback,
uint32_t *cbdata, tpPESession psessionEntry);
-
-void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
- uint8_t *frame, uint32_t frameLen,
- uint16_t sessionId, uint32_t rxChan,
- tpPESession psessionEntry, int8_t rxRssi);
+/*
+ * lim_send_sme_mgmt_frame_ind() - Function to send mgmt frame ind to HDD
+ * @mac_ctx: Pointer to Global MAC structure
+ * @frame_type: Type of mgmt frame
+ * @frame: Frame pointer
+ * @frame_len: Length og mgmt frame
+ * @session_id: session id
+ * @rx_chan: Channel of where packet is received
+ * @psession_entry: PE Session Entry
+ * @rx_rssi: rssi value
+ * @rx_flags: RXMGMT flags to be set for the frame. Defined in enum rxmgmt_flags
+ */
+void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal mac_ctx, uint8_t frame_type,
+ uint8_t *frame, uint32_t frame_len,
+ uint16_t session_id, uint32_t rx_chan,
+ tpPESession psession_entry,
+ int8_t rx_rssi, enum rxmgmt_flags rx_flags);
void lim_process_remain_on_chn_timeout(tpAniSirGlobal pMac);
void lim_process_insert_single_shot_noa_timeout(tpAniSirGlobal pMac);
void lim_convert_active_channel_to_passive_channel(tpAniSirGlobal pMac);
@@ -1040,4 +1053,49 @@ void lim_send_mgmt_frame_tx(tpAniSirGlobal mac_ctx,
*/
bool lim_p2p_check_oui_and_force_1x1(tpAniSirGlobal mac_ctx,
uint8_t *assoc_ie, uint32_t assoc_ie_len);
+
+/**
+ * lim_process_assoc_cleanup() - frees up resources used in function
+ * lim_process_assoc_req_frame()
+ * @mac_ctx: pointer to Global MAC structure
+ * @session: pointer to pe session entry
+ * @assoc_req: pointer to ASSOC/REASSOC Request frame
+ * @sta_ds: station dph entry
+ * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above
+ *
+ * Frees up resources used in function lim_process_assoc_req_frame
+ *
+ * Return: void
+ */
+void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx,
+ tpPESession session,
+ tpSirAssocReq assoc_req,
+ tpDphHashNode sta_ds,
+ bool assoc_req_copied);
+
+/**
+ * lim_send_assoc_ind_to_sme() - Initialize PE data structures and send assoc
+ * indication to SME.
+ * @mac_ctx: Pointer to Global MAC structure
+ * @session: pe session entry
+ * @sub_type: Indicates whether it is Association Request(=0) or Reassociation
+ * Request(=1) frame
+ * @hdr: A pointer to the MAC header
+ * @assoc_req: pointer to ASSOC/REASSOC Request frame
+ * @pmf_connection: flag indicating pmf connection
+ * @assoc_req_copied: boolean to indicate if assoc req was copied to tmp above
+ * @dup_entry: flag indicating if duplicate entry found
+ * @force_1x1: flag to indicate if the STA nss needs to be downgraded to 1x1
+ *
+ * Return: true on success, and false otherwise
+ */
+bool lim_send_assoc_ind_to_sme(tpAniSirGlobal mac_ctx,
+ tpPESession session,
+ uint8_t sub_type,
+ tpSirMacMgmtHdr hdr,
+ tpSirAssocReq assoc_req,
+ bool pmf_connection,
+ bool *assoc_req_copied,
+ bool dup_entry,
+ bool force_1x1);
#endif /* __LIM_TYPES_H */
diff --git a/core/mac/src/pe/nan/nan_datapath.c b/core/mac/src/pe/nan/nan_datapath.c
index 6a38d72a050e..34d73712b7d9 100644
--- a/core/mac/src/pe/nan/nan_datapath.c
+++ b/core/mac/src/pe/nan/nan_datapath.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019,2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -158,9 +158,8 @@ static QDF_STATUS lim_handle_ndp_indication_event(tpAniSirGlobal mac_ctx,
goto ndp_indication_failed;
}
}
- if (NDP_ROLE_RESPONDER == ndp_ind->role)
- lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INDICATION,
- ndp_ind, sizeof(*ndp_ind), 0);
+ lim_send_ndp_event_to_sme(mac_ctx, eWNI_SME_NDP_INDICATION,
+ ndp_ind, sizeof(*ndp_ind), 0);
/*
* With NDP indication if peer does not exists already add_sta is
* executed resulting in new peer else no action is taken. Note that
@@ -170,13 +169,8 @@ static QDF_STATUS lim_handle_ndp_indication_event(tpAniSirGlobal mac_ctx,
* used by service layer to identify failure.
*/
ndp_indication_failed:
- /*
- * Free config if failure or for NDP_ROLE_INITIATOR role
- * As for success responder case this info is sent till HDD
- * and will be freed in sme.
- */
- if (status != QDF_STATUS_SUCCESS ||
- NDP_ROLE_INITIATOR == ndp_ind->role) {
+ /* free config and app info if failure */
+ if (status != QDF_STATUS_SUCCESS) {
qdf_mem_free(ndp_ind->ndp_config.ndp_cfg);
qdf_mem_free(ndp_ind->ndp_info.ndp_app_info);
ndp_ind->ndp_config.ndp_cfg = NULL;
diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c
index f5aadcca0c81..7beb7bb15e0c 100644
--- a/core/sap/src/sap_fsm.c
+++ b/core/sap/src/sap_fsm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -4844,6 +4844,7 @@ static QDF_STATUS sap_get_channel_list(ptSapContext sap_ctx,
tSapChSelSpectInfo spect_info_obj = { NULL, 0 };
uint16_t ch_width;
uint8_t i;
+ uint8_t ch;
if (NULL == hal) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
@@ -4958,10 +4959,8 @@ static QDF_STATUS sap_get_channel_list(ptSapContext sap_ctx,
continue;
}
-#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
- uint8_t ch;
-
ch = CDS_CHANNEL_NUM(loop_count);
+#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
if ((sap_ctx->acs_cfg->skip_scan_status ==
eSAP_DO_PAR_ACS_SCAN)) {
if ((ch >= sap_ctx->acs_cfg->skip_scan_range1_stch &&
@@ -4991,7 +4990,7 @@ static QDF_STATUS sap_get_channel_list(ptSapContext sap_ctx,
ch_count, ch);
}
#else
- list[ch_count] = CDS_CHANNEL_NUM(loop_count);
+ list[ch_count] = ch;
ch_count++;
#endif
}
diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h
index fef3c05dc7a3..32022b370d32 100644
--- a/core/sme/inc/csr_api.h
+++ b/core/sme/inc/csr_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -360,6 +360,11 @@ typedef struct tagCsrEseCckmIe {
uint8_t cckmIe[DOT11F_IE_RSN_MAX_LEN];
uint8_t cckmIeLen;
} tCsrEseCckmIe;
+
+#define reset_cckm_info(cckm_info) \
+ qdf_mem_zero((cckm_info), sizeof(tCsrEseCckmInfo))
+#else
+#define reset_cckm_info(cckm_info)
#endif /* FEATURE_WLAN_ESE */
typedef struct sCsrChannel_ {
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 55674fcc965e..080249e76944 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -2309,14 +2309,20 @@ QDF_STATUS sme_send_mgmt_tx(tHalHandle hal, uint8_t session_id,
* @hal: The handle returned by mac_open
* @session_id: session id
* @sae_status: status of SAE authentication
+ * @peer_mac_addr: mac address of the peer to be authenticated
*
* Return: QDF_STATUS
*/
-QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id,
- uint8_t sae_status);
+QDF_STATUS sme_handle_sae_msg(tHalHandle hal,
+ uint8_t session_id,
+ uint8_t sae_status,
+ struct qdf_mac_addr peer_mac_addr);
#else
-static inline QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id,
- uint8_t sae_status)
+static inline
+QDF_STATUS sme_handle_sae_msg(tHalHandle hal,
+ uint8_t session_id,
+ uint8_t sae_status,
+ struct qdf_mac_addr peer_mac_addr)
{
return QDF_STATUS_SUCCESS;
}
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index ff32941eff97..4eec3b9da324 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -19487,8 +19487,10 @@ QDF_STATUS sme_send_mgmt_tx(tHalHandle hal, uint8_t session_id,
}
#ifdef WLAN_FEATURE_SAE
-QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id,
- uint8_t sae_status)
+QDF_STATUS sme_handle_sae_msg(tHalHandle hal,
+ uint8_t session_id,
+ uint8_t sae_status,
+ struct qdf_mac_addr peer_mac_addr)
{
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
@@ -19505,9 +19507,13 @@ QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id,
sae_msg->length = sizeof(*sae_msg);
sae_msg->session_id = session_id;
sae_msg->sae_status = sae_status;
- sme_debug("SAE: sae_status %d session_id %d",
- sae_msg->sae_status,
- sae_msg->session_id);
+ qdf_mem_copy(sae_msg->peer_mac_addr,
+ peer_mac_addr.bytes,
+ MAC_ADDR_LEN);
+ sme_debug("SAE: sae_status %d session_id %d Peer: "
+ MAC_ADDRESS_STR, sae_msg->sae_status,
+ sae_msg->session_id,
+ MAC_ADDR_ARRAY(sae_msg->peer_mac_addr));
qdf_status = cds_send_mb_message_to_mac(sae_msg);
}
diff --git a/core/sme/src/common/sme_ft_api.c b/core/sme/src/common/sme_ft_api.c
index b34bdaec3a7b..516552d0e004 100644
--- a/core/sme/src/common/sme_ft_api.c
+++ b/core/sme/src/common/sme_ft_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017,2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017,2019-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -487,7 +487,7 @@ void sme_reset_key(tHalHandle mac_handle, uint32_t vdev_id)
return;
qdf_mem_zero(&session->psk_pmk, sizeof(session->psk_pmk));
session->pmk_len = 0;
- qdf_mem_zero(&session->eseCckmInfo, sizeof(session->eseCckmInfo));
+ reset_cckm_info(&session->eseCckmInfo);
}
/* Reset the FT context. */
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 52560b37b560..3d5b76fddf06 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -47,7 +47,9 @@
#include "pld_common.h"
#include "qdf_crypto.h"
#include <wlan_logging_sock_svc.h>
+#include <cds_ieee80211_common.h>
+#define RSN_AUTH_KEY_MGMT_SAE RSN_SEL(AKM_SUITE_TYPE_SAE)
#define MAX_PWR_FCC_CHAN_12 8
#define MAX_PWR_FCC_CHAN_13 2
@@ -11675,6 +11677,54 @@ static QDF_STATUS csr_send_reset_ap_caps_changed(tpAniSirGlobal pMac,
return status;
}
+static bool csr_is_sae_akm_present(tDot11fIERSN * const rsn_ie)
+{
+ uint16_t i;
+
+ if (rsn_ie->akm_suite_cnt > 6) {
+ sme_debug("Invalid akm_suite_cnt in Rx RSN IE");
+ return false;
+ }
+
+ for (i = 0; i < rsn_ie->akm_suite_cnt; i++) {
+ if (LE_READ_4(rsn_ie->akm_suite[i]) == RSN_AUTH_KEY_MGMT_SAE) {
+ sme_debug("SAE AKM present");
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool csr_is_sae_peer_allowed(tpAniSirGlobal mac,
+ tSirSmeAssocInd *assoc_ind,
+ tCsrRoamSession *session,
+ tSirMacAddr peer_mac_addr,
+ tDot11fIERSN *rsn_ie,
+ tSirMacStatusCodes *mac_status_code)
+{
+ bool is_allowed = false;
+
+ /* Allow the peer if it's SAE authenticated */
+ if (assoc_ind->is_sae_authenticated)
+ return true;
+
+ /* Allow the peer with valid PMKID */
+ if (!rsn_ie->pmkid_count) {
+ *mac_status_code = eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
+ sme_debug("No PMKID present in RSNIE; Tried to use SAE AKM after non-SAE authentication");
+ } else if (csr_is_pmkid_found_for_peer(mac, session, peer_mac_addr,
+ &rsn_ie->pmkid[0][0],
+ rsn_ie->pmkid_count)) {
+ sme_debug("Valid PMKID found for SAE peer");
+ is_allowed = true;
+ } else {
+ *mac_status_code = eSIR_MAC_INVALID_PMKID;
+ sme_debug("No valid PMKID found for SAE peer");
+ }
+
+ return is_allowed;
+}
+
static void
csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr)
{
@@ -11684,6 +11734,7 @@ csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr)
tCsrRoamInfo *roam_info_ptr = NULL;
tSirSmeAssocInd *pAssocInd;
tCsrRoamInfo roam_info;
+ tSirMacStatusCodes mac_status_code = eSIR_MAC_SUCCESS_STATUS;
qdf_mem_set(&roam_info, sizeof(roam_info), 0);
sme_debug("Receive WNI_SME_ASSOC_IND from SME");
@@ -11756,13 +11807,35 @@ csr_roam_chk_lnk_assoc_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr)
status = csr_roam_call_callback(mac_ctx, sessionId,
roam_info_ptr, 0, eCSR_ROAM_INFRA_IND,
eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND);
- if (!QDF_IS_STATUS_SUCCESS(status))
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
/* Refused due to Mac filtering */
roam_info_ptr->statusCode = eSIR_SME_ASSOC_REFUSED;
+ } else if (pAssocInd->rsnIE.length) {
+ tDot11fIERSN rsn_ie = {0};
+
+ if (dot11f_unpack_ie_rsn(mac_ctx,
+ pAssocInd->rsnIE.rsnIEdata + 2,
+ pAssocInd->rsnIE.length - 2,
+ &rsn_ie, false)
+ != DOT11F_PARSE_SUCCESS ||
+ (csr_is_sae_akm_present(&rsn_ie) &&
+ !csr_is_sae_peer_allowed(mac_ctx, pAssocInd,
+ session,
+ pAssocInd->peerMacAddr,
+ &rsn_ie,
+ &mac_status_code))) {
+ status = QDF_STATUS_E_INVAL;
+ roam_info_ptr->statusCode =
+ eSIR_SME_ASSOC_REFUSED;
+ sme_debug("SAE peer not allowed: Status: %d",
+ mac_status_code);
+ }
+ }
}
/* Send Association completion message to PE */
- status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status);
+ status = csr_send_assoc_cnf_msg(mac_ctx, pAssocInd, status,
+ mac_status_code);
/*
* send a message to CSR itself just to avoid the EAPOL frames going
* OTA before association response
@@ -17102,8 +17175,10 @@ QDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac,
return status;
}
-QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd
- pAssocInd, QDF_STATUS Halstatus)
+QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac,
+ tpSirSmeAssocInd pAssocInd,
+ QDF_STATUS Halstatus,
+ tSirMacStatusCodes mac_status_code)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tSirSmeAssocCnf *pMsg;
@@ -17116,10 +17191,12 @@ QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd
return QDF_STATUS_E_NOMEM;
pMsg->messageType = eWNI_SME_ASSOC_CNF;
pMsg->length = sizeof(tSirSmeAssocCnf);
- if (QDF_IS_STATUS_SUCCESS(Halstatus))
+ if (QDF_IS_STATUS_SUCCESS(Halstatus)) {
pMsg->statusCode = eSIR_SME_SUCCESS;
- else
+ } else {
pMsg->statusCode = eSIR_SME_ASSOC_REFUSED;
+ pMsg->mac_status_code = mac_status_code;
+ }
/* bssId */
qdf_mem_copy(pMsg->bssid.bytes, pAssocInd->bssId,
QDF_MAC_ADDR_SIZE);
diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h
index e417673842ae..e823a7102398 100644
--- a/core/sme/src/csr/csr_inside_api.h
+++ b/core/sme/src/csr/csr_inside_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -475,9 +475,10 @@ QDF_STATUS csr_send_mb_disassoc_cnf_msg(tpAniSirGlobal pMac,
tpSirSmeDisassocInd pDisassocInd);
QDF_STATUS csr_send_mb_deauth_cnf_msg(tpAniSirGlobal pMac,
tpSirSmeDeauthInd pDeauthInd);
-QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac, tpSirSmeAssocInd
- pAssocInd,
- QDF_STATUS status);
+QDF_STATUS csr_send_assoc_cnf_msg(tpAniSirGlobal pMac,
+ tpSirSmeAssocInd pAssocInd,
+ QDF_STATUS status,
+ tSirMacStatusCodes mac_status_code);
QDF_STATUS csr_send_assoc_ind_to_upper_layer_cnf_msg(tpAniSirGlobal pMac,
tpSirSmeAssocInd pAssocInd,
QDF_STATUS Halstatus,
@@ -1301,4 +1302,20 @@ bool csr_lookup_pmkid_using_bssid(tpAniSirGlobal mac,
tPmkidCacheInfo *pmk_cache,
uint32_t *index);
+/**
+ * csr_is_pmkid_found_for_peer() - check if pmkid sent by peer is present
+ * in PMK cache. Used in SAP mode.
+ * @mac: pointer to mac
+ * @session: sme session pointer
+ * @peer_mac_addr: mac address of the connecting peer
+ * @pmkid: pointer to pmkid(s) send by peer
+ * @pmkid_count: number of pmkids sent by peer
+ *
+ * Return: true if pmkid is found else false
+ */
+bool csr_is_pmkid_found_for_peer(tpAniSirGlobal mac,
+ tCsrRoamSession *session,
+ tSirMacAddr peer_mac_addr,
+ uint8_t *pmkid, uint16_t pmkid_count);
+
#endif /* CSR_INSIDE_API_H__ */
diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c
index 7958cba2a5ea..7f32969e3f89 100644
--- a/core/sme/src/csr/csr_util.c
+++ b/core/sme/src/csr/csr_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -3098,6 +3098,32 @@ static void csr_check_sae_auth(tpAniSirGlobal mac_ctx,
}
#endif
+bool csr_is_pmkid_found_for_peer(tpAniSirGlobal mac,
+ tCsrRoamSession *session,
+ tSirMacAddr peer_mac_addr,
+ uint8_t *pmkid,
+ uint16_t pmkid_count)
+{
+ uint32_t i, index;
+ uint8_t *session_pmkid;
+ tPmkidCacheInfo pmkid_cache;
+
+ qdf_mem_zero(&pmkid_cache, sizeof(pmkid_cache));
+ qdf_mem_copy(pmkid_cache.BSSID.bytes, peer_mac_addr, MAC_ADDR_LEN);
+
+ if (!csr_lookup_pmkid_using_bssid(mac, session, &pmkid_cache, &index))
+ return false;
+ session_pmkid = &session->PmkidCacheInfo[index].PMKID[0];
+ for (i = 0; i < pmkid_count; i++) {
+ if (!qdf_mem_cmp(pmkid + (i * CSR_RSN_PMKID_SIZE),
+ session_pmkid, CSR_RSN_PMKID_SIZE))
+ return true;
+ }
+
+ sme_debug("PMKID in PmkidCacheInfo doesn't match with PMKIDs of peer");
+ return false;
+}
+
/**
* csr_get_rsn_information() - to get RSN infomation
* @hal: pointer to HAL
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index 161609e3e178..3bf53e023984 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -11133,6 +11133,9 @@ int wma_unified_power_debug_stats_event_handler(void *handle,
mac->sme.power_stats_resp_callback(power_stats_results,
mac->sme.power_debug_stats_context);
+
+ mac->sme.power_stats_resp_callback = NULL;
+ mac->sme.power_debug_stats_context = NULL;
qdf_mem_free(power_stats_results);
return 0;
}