summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-06-28 04:04:52 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-06-28 04:04:52 -0600
commit40b5475e8b378f2b804e1cf2619523bf69b867bd (patch)
treedf9f8451f31521a86223c4fbf712dc636ed194a0
parent05e466a76f1864fe082aeb4751dc73ba79674440 (diff)
parentef65cf4adc4d15ca88bab1a7136a367cb4f54504 (diff)
Promotion of wlan-cld3.driver.lnx.1.1-00024.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1029145 I302ad442f660feb795d7a8f1353b5d820d26aac8 qcacld-3.0: Populate extended caps coming for each phy t 1029145 I3ad9b474c281f3dd371eb2b88b71e8af59fcd66d qcacld-3.0: Derive HT and VHT caps from given per PHY ca 688141 Ib5358ac9729a133e413d2f86d11a09b1e86c7416 Release 5.1.0.13 1025390 I8b3df2259f71cf51b8ffc8b9a50edad7fea81d13 qcacld-3.0: Don't set operating channel before ROC gets 869026 I5cbf17a14ab6becad6cf5765ae5039fc284dc309 qcacld-3.0: Add support for NSS configurability 1031855 I4a08717abce2a0ecbe4055360fd8d31c3e50a701 qcacld-3.0: Sanitize SAP context before extracting the h 996988 I995ea9c391372515faabe5086b638f254b6b93d7 qcacld-3.0: Add TDLS connection tracker in WLAN host 1031855 I6f722dcc4ab671fef010c816a7c7d38fc1bdebe4 qcacld-3.0: Validate SAP context before access in callba 1016872 I55028533ebbf03910755da1b35c2fa57d97ce43b qcacld-3.0: Send disconnect event to upper layers upon d 1020291 I220d2c1909a44fd7edb46127daec1165fca71ebe qcacld-3.0: Include appropriate auth info for roaming 1017437 Ia59fa5ba326504eb54e14d44f42a335c6b835ee4 qcacld-3.0: Enhance data path related statistics 1029145 I8a3659f20414851cb394395225c301a90cd94f64 qcacld-3.0: Reset gEnableRXLDPC to mitigate hardware lim 930870 I4632c1b4770e6b2f301d67f37005585aef401ab6 qcacld-3.0: Implement cfg80211 abort scan API 1033129 I3b752c365e09f08104fa871c29e2629c1873b3fc qcacld-3.0: Send wow wake event bitmap properly to fw Change-Id: I0b8f99f01cafa482541354bfbebf92eb823b2847 CRs-Fixed: 1025390, 1016872, 996988, 1020291, 688141, 1017437, 930870, 869026, 1031855, 1033129, 1029145
-rw-r--r--config/WCNSS_qcom_cfg.ini2
-rw-r--r--core/cds/inc/cds_concurrency.h1
-rw-r--r--core/cds/src/cds_concurrency.c53
-rw-r--r--core/dp/htt/htt_rx.c5
-rw-r--r--core/dp/ol/inc/ol_txrx_stats.h17
-rw-r--r--core/dp/txrx/ol_rx.c12
-rw-r--r--core/dp/txrx/ol_rx.h3
-rw-r--r--core/dp/txrx/ol_tx.c23
-rw-r--r--core/dp/txrx/ol_tx_desc.c2
-rw-r--r--core/dp/txrx/ol_txrx.c104
-rw-r--r--core/dp/txrx/ol_txrx_flow_control.c28
-rw-r--r--core/dp/txrx/ol_txrx_internal.h53
-rw-r--r--core/dp/txrx/ol_txrx_types.h4
-rw-r--r--core/hdd/inc/wlan_hdd_cfg.h23
-rw-r--r--core/hdd/inc/wlan_hdd_main.h10
-rw-r--r--core/hdd/inc/wlan_hdd_tdls.h52
-rw-r--r--core/hdd/src/wlan_hdd_assoc.c24
-rw-r--r--core/hdd/src/wlan_hdd_cfg.c68
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c14
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h19
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.c4
-rw-r--r--core/hdd/src/wlan_hdd_main.c170
-rw-r--r--core/hdd/src/wlan_hdd_power.c3
-rw-r--r--core/hdd/src/wlan_hdd_scan.c57
-rw-r--r--core/hdd/src/wlan_hdd_scan.h8
-rw-r--r--core/hdd/src/wlan_hdd_tdls.c889
-rw-r--r--core/hdd/src/wlan_hdd_tx_rx.c52
-rw-r--r--core/hdd/src/wlan_hdd_wext.c2
-rw-r--r--core/mac/inc/ani_global.h48
-rw-r--r--core/mac/inc/qwlan_version.h4
-rw-r--r--core/mac/inc/sir_api.h21
-rw-r--r--core/mac/inc/sir_mac_prot_def.h6
-rw-r--r--core/mac/inc/wni_api.h1
-rw-r--r--core/mac/src/include/parser_api.h3
-rw-r--r--core/mac/src/include/sir_params.h1
-rw-r--r--core/mac/src/pe/include/lim_session.h1
-rw-r--r--core/mac/src/pe/lim/lim_assoc_utils.c17
-rw-r--r--core/mac/src/pe/lim/lim_process_message_queue.c1
-rw-r--r--core/mac/src/pe/lim/lim_process_sme_req_messages.c314
-rw-r--r--core/sap/inc/sap_api.h3
-rw-r--r--core/sap/src/sap_api_link_cntl.c17
-rw-r--r--core/sap/src/sap_fsm.c2
-rw-r--r--core/sap/src/sap_internal.h4
-rw-r--r--core/sap/src/sap_module.c171
-rw-r--r--core/sme/inc/sme_api.h5
-rw-r--r--core/sme/inc/sme_inside.h3
-rw-r--r--core/sme/src/common/sme_api.c109
-rw-r--r--core/sme/src/csr/csr_api_roam.c77
-rw-r--r--core/wma/inc/wma.h61
-rw-r--r--core/wma/inc/wma_if.h27
-rw-r--r--core/wma/inc/wma_internal.h5
-rw-r--r--core/wma/inc/wma_tgt_cfg.h2
-rw-r--r--core/wma/inc/wma_types.h5
-rw-r--r--core/wma/src/wma_dev_if.c2
-rw-r--r--core/wma/src/wma_features.c2
-rw-r--r--core/wma/src/wma_main.c571
-rw-r--r--core/wma/src/wma_scan_roam.c184
-rw-r--r--core/wma/src/wma_utils.c19
58 files changed, 3078 insertions, 310 deletions
diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini
index e0b3a3d56ea1..51a4cc7b9559 100644
--- a/config/WCNSS_qcom_cfg.ini
+++ b/config/WCNSS_qcom_cfg.ini
@@ -366,7 +366,7 @@ gEnableRXSTBC=1
gEnableTXSTBC=1
# 1=enable rx LDPC; 0=disable
-gEnableRXLDPC=1
+gEnableRXLDPC=0
#Enable/Disable Tx beamforming
gTxBFEnable=1
diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h
index e7132c8700da..08e4d8fe4bbf 100644
--- a/core/cds/inc/cds_concurrency.h
+++ b/core/cds/inc/cds_concurrency.h
@@ -554,6 +554,7 @@ struct cds_conc_connection_info {
bool cds_is_connection_in_progress(void);
void cds_dump_concurrency_info(void);
+void cds_set_tdls_ct_mode(hdd_context_t *hdd_ctx);
void cds_set_concurrency_mode(enum tQDF_ADAPTER_MODE mode);
void cds_clear_concurrency_mode(enum tQDF_ADAPTER_MODE mode);
uint32_t cds_get_connection_count(void);
diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c
index ec9360ce10fb..7fb5455f0b8b 100644
--- a/core/cds/src/cds_concurrency.c
+++ b/core/cds/src/cds_concurrency.c
@@ -3372,6 +3372,41 @@ void cds_dump_concurrency_info(void)
}
/**
+ * cds_set_tdls_ct_mode() - Set the tdls connection tracker mode
+ * @hdd_ctx: hdd context
+ *
+ * This routine is called to set the tdls connection tracker operation status
+ *
+ * Return: NONE
+ */
+void cds_set_tdls_ct_mode(hdd_context_t *hdd_ctx)
+{
+ bool state = false;
+
+ /* If any concurrency is detected, skip tdls pkt tracker */
+ if (((1 << QDF_STA_MODE) == hdd_ctx->concurrency_mode) &&
+ (hdd_ctx->no_of_active_sessions[QDF_STA_MODE] == 1) &&
+ (hdd_ctx->config->fEnableTDLSImplicitTrigger) &&
+ (eTDLS_SUPPORT_DISABLED != hdd_ctx->tdls_mode)) {
+ if (hdd_ctx->config->fTDLSExternalControl) {
+ if (hdd_ctx->tdls_external_peer_count)
+ state = true;
+ goto set_state;
+ } else {
+ state = true;
+ }
+ }
+
+set_state:
+ mutex_lock(&hdd_ctx->tdls_lock);
+ hdd_ctx->enable_tdls_connection_tracker = state;
+ mutex_unlock(&hdd_ctx->tdls_lock);
+
+ cds_info("enable_tdls_connection_tracker %d",
+ hdd_ctx->enable_tdls_connection_tracker);
+}
+
+/**
* cds_set_concurrency_mode() - To set concurrency mode
* @mode: adapter mode
*
@@ -3402,6 +3437,10 @@ void cds_set_concurrency_mode(enum tQDF_ADAPTER_MODE mode)
default:
break;
}
+
+ /* set tdls connection tracker state */
+ cds_set_tdls_ct_mode(hdd_ctx);
+
cds_info("concurrency_mode = 0x%x Number of open sessions for mode %d = %d",
hdd_ctx->concurrency_mode, mode,
hdd_ctx->no_of_open_sessions[mode]);
@@ -3438,6 +3477,10 @@ void cds_clear_concurrency_mode(enum tQDF_ADAPTER_MODE mode)
default:
break;
}
+
+ /* set tdls connection tracker state */
+ cds_set_tdls_ct_mode(hdd_ctx);
+
cds_info("concurrency_mode = 0x%x Number of open sessions for mode %d = %d",
hdd_ctx->concurrency_mode, mode,
hdd_ctx->no_of_open_sessions[mode]);
@@ -3550,8 +3593,13 @@ void cds_incr_active_session(enum tQDF_ADAPTER_MODE mode,
default:
break;
}
+
+ /* set tdls connection tracker state */
+ cds_set_tdls_ct_mode(hdd_ctx);
+
cds_info("No.# of active sessions for mode %d = %d",
mode, hdd_ctx->no_of_active_sessions[mode]);
+
/*
* Get PCL logic makes use of the connection info structure.
* Let us set the PCL to the FW before updating the connection
@@ -3826,8 +3874,13 @@ void cds_decr_active_session(enum tQDF_ADAPTER_MODE mode,
default:
break;
}
+
+ /* set tdls connection tracker state */
+ cds_set_tdls_ct_mode(hdd_ctx);
+
cds_info("No.# of active sessions for mode %d = %d",
mode, hdd_ctx->no_of_active_sessions[mode]);
+
cds_decr_connection_count(session_id);
qdf_mutex_release(&cds_ctx->qdf_conc_list_lock);
}
diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c
index 0a1d82983175..641e2c09a65c 100644
--- a/core/dp/htt/htt_rx.c
+++ b/core/dp/htt/htt_rx.c
@@ -1940,7 +1940,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
uint8_t *rx_ind_data;
uint32_t *msg_word;
unsigned int msdu_count = 0;
- uint8_t offload_ind;
+ uint8_t offload_ind, frag_ind;
struct htt_host_rx_desc_base *rx_desc;
uint8_t peer_id;
@@ -1952,11 +1952,12 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
*(u_int32_t *)rx_ind_data);
offload_ind = HTT_RX_IN_ORD_PADDR_IND_OFFLOAD_GET(*msg_word);
+ frag_ind = HTT_RX_IN_ORD_PADDR_IND_FRAG_GET(*msg_word);
/* Get the total number of MSDUs */
msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1));
HTT_RX_CHECK_MSDU_COUNT(msdu_count);
- ol_rx_update_histogram_stats(msdu_count);
+ ol_rx_update_histogram_stats(msdu_count, frag_ind, offload_ind);
msg_word =
(uint32_t *) (rx_ind_data + HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES);
diff --git a/core/dp/ol/inc/ol_txrx_stats.h b/core/dp/ol/inc/ol_txrx_stats.h
index 27a49ef03c09..842924e1c861 100644
--- a/core/dp/ol/inc/ol_txrx_stats.h
+++ b/core/dp/ol/inc/ol_txrx_stats.h
@@ -53,6 +53,9 @@ struct ol_txrx_stats_tso_msdu {
struct qdf_tso_seg_t tso_segs[NUM_MAX_TSO_SEGS];
uint8_t num_seg;
uint8_t tso_seg_idx;
+ uint32_t total_len;
+ uint32_t gso_size;
+ uint8_t nr_frags;
};
struct ol_txrx_stats_tso_info {
@@ -81,6 +84,15 @@ struct ol_txrx_stats_tx_dropped {
struct ol_txrx_stats_elem no_ack;
};
+struct ol_txrx_tso_histogram {
+ uint32_t pkts_1;
+ uint32_t pkts_2_5;
+ uint32_t pkts_6_10;
+ uint32_t pkts_11_15;
+ uint32_t pkts_16_20;
+ uint32_t pkts_20_plus;
+};
+
struct ol_txrx_stats_tx_histogram {
uint32_t pkts_1;
uint32_t pkts_2_10;
@@ -95,12 +107,15 @@ struct ol_txrx_stats_tx_tso {
struct ol_txrx_stats_elem tso_pkts;
#if defined(FEATURE_TSO)
struct ol_txrx_stats_tso_info tso_info;
+ struct ol_txrx_tso_histogram tso_hist;
#endif
};
struct ol_txrx_stats_tx {
/* MSDUs given to the txrx layer by the management stack */
struct ol_txrx_stats_elem mgmt;
+ /* MSDUs received from the stack */
+ struct ol_txrx_stats_elem from_stack;
/* MSDUs successfully sent across the WLAN */
struct ol_txrx_stats_elem delivered;
struct ol_txrx_stats_tx_dropped dropped;
@@ -139,6 +154,8 @@ struct ol_txrx_stats_rx {
struct ol_txrx_stats_elem dropped_peer_invalid;
struct ol_txrx_stats_rx_ibss_fwd intra_bss_fwd;
struct ol_txrx_stats_rx_histogram rx_ind_histogram;
+ uint32_t msdus_with_frag_ind;
+ uint32_t msdus_with_offload_ind;
};
struct ol_txrx_stats {
struct ol_txrx_stats_tx tx;
diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c
index 52b894a49a53..db52497615f8 100644
--- a/core/dp/txrx/ol_rx.c
+++ b/core/dp/txrx/ol_rx.c
@@ -104,10 +104,13 @@ void ol_rx_trigger_restore(htt_pdev_handle htt_pdev, qdf_nbuf_t head_msdu,
/**
* ol_rx_update_histogram_stats() - update rx histogram statistics
* @msdu_count: msdu count
+ * @frag_ind: fragment indication set
+ * @offload_ind: offload indication set
*
* Return: none
*/
-void ol_rx_update_histogram_stats(uint32_t msdu_count)
+void ol_rx_update_histogram_stats(uint32_t msdu_count, uint8_t frag_ind,
+ uint8_t offload_ind)
{
struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
@@ -134,6 +137,13 @@ void ol_rx_update_histogram_stats(uint32_t msdu_count)
} else if (msdu_count == 1) {
TXRX_STATS_ADD(pdev, pub.rx.rx_ind_histogram.pkts_1, 1);
}
+
+ if (frag_ind)
+ TXRX_STATS_ADD(pdev, pub.rx.msdus_with_frag_ind, msdu_count);
+
+ if (offload_ind)
+ TXRX_STATS_ADD(pdev, pub.rx.msdus_with_offload_ind, msdu_count);
+
}
static void ol_rx_process_inv_peer(ol_txrx_pdev_handle pdev,
diff --git a/core/dp/txrx/ol_rx.h b/core/dp/txrx/ol_rx.h
index 5c6045e1ff8f..786f94e2feaf 100644
--- a/core/dp/txrx/ol_rx.h
+++ b/core/dp/txrx/ol_rx.h
@@ -58,7 +58,8 @@ void
ol_rx_offload_paddr_deliver_ind_handler(htt_pdev_handle htt_pdev,
uint32_t msdu_count,
uint32_t *msg_word);
-void ol_rx_update_histogram_stats(uint32_t msdu_count);
+void ol_rx_update_histogram_stats(uint32_t msdu_count,
+ uint8_t frag_ind, uint8_t offload_ind);
void
ol_rx_mic_error_handler(
diff --git a/core/dp/txrx/ol_tx.c b/core/dp/txrx/ol_tx.c
index c2c79fb0b232..40374f043050 100644
--- a/core/dp/txrx/ol_tx.c
+++ b/core/dp/txrx/ol_tx.c
@@ -247,6 +247,14 @@ qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
}
segments = msdu_info.tso_info.num_segs;
+ TXRX_STATS_TSO_HISTOGRAM(vdev->pdev, segments);
+ TXRX_STATS_TSO_GSO_SIZE_UPDATE(vdev->pdev,
+ qdf_nbuf_tcp_tso_size(msdu));
+ TXRX_STATS_TSO_TOTAL_LEN_UPDATE(vdev->pdev,
+ qdf_nbuf_len(msdu));
+ TXRX_STATS_TSO_NUM_FRAGS_UPDATE(vdev->pdev,
+ qdf_nbuf_get_nr_frags(msdu));
+
/*
* The netbuf may get linked into a different list inside the
@@ -275,6 +283,8 @@ qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info);
+ TXRX_STATS_MSDU_INCR(vdev->pdev, tx.from_stack, msdu);
+
/*
* If debug display is enabled, show the meta-data being
* downloaded to the target via the HTT tx descriptor.
@@ -328,6 +338,8 @@ qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
msdu_info.peer = NULL;
ol_tx_prepare_ll(tx_desc, vdev, msdu, &msdu_info);
+ TXRX_STATS_MSDU_INCR(vdev->pdev, tx.from_stack, msdu);
+
/*
* If debug display is enabled, show the meta-data being
* downloaded to the target via the HTT tx descriptor.
@@ -531,6 +543,13 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
}
segments = msdu_info.tso_info.num_segs;
+ TXRX_STATS_TSO_HISTOGRAM(vdev->pdev, segments);
+ TXRX_STATS_TSO_GSO_SIZE_UPDATE(vdev->pdev,
+ qdf_nbuf_tcp_tso_size(msdu));
+ TXRX_STATS_TSO_TOTAL_LEN_UPDATE(vdev->pdev,
+ qdf_nbuf_len(msdu));
+ TXRX_STATS_TSO_NUM_FRAGS_UPDATE(vdev->pdev,
+ qdf_nbuf_get_nr_frags(msdu));
/*
* The netbuf may get linked into a different list
@@ -580,6 +599,8 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
pkt_download_len, ep_id,
&msdu_info);
+ TXRX_STATS_MSDU_INCR(pdev, tx.from_stack, msdu);
+
if (qdf_likely(tx_desc)) {
DPTRACE(qdf_dp_trace_ptr(msdu,
QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD,
@@ -684,6 +705,8 @@ ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list)
pkt_download_len, ep_id,
&msdu_info);
+ TXRX_STATS_MSDU_INCR(pdev, tx.from_stack, msdu);
+
if (qdf_likely(tx_desc)) {
DPTRACE(qdf_dp_trace_ptr(msdu,
QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD,
diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c
index 04d18c49da80..8da961622a9b 100644
--- a/core/dp/txrx/ol_tx_desc.c
+++ b/core/dp/txrx/ol_tx_desc.c
@@ -236,8 +236,8 @@ struct ol_tx_desc_t *ol_tx_desc_alloc(struct ol_txrx_pdev_t *pdev,
ol_tx_desc_sanity_checks(pdev, tx_desc);
ol_tx_desc_compute_delay(tx_desc);
} else {
+ pool->pkt_drop_no_desc++;
qdf_spin_unlock_bh(&pool->flow_pool_lock);
- pdev->pool_stats.pkt_drop_no_desc++;
}
} else {
pdev->pool_stats.pkt_drop_no_pool++;
diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c
index 09cffd3d559a..fcd1831a99ec 100644
--- a/core/dp/txrx/ol_txrx.c
+++ b/core/dp/txrx/ol_txrx.c
@@ -3521,16 +3521,41 @@ void ol_txrx_stats_display_tso(ol_txrx_pdev_handle pdev)
int seg_idx;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ "TSO Statistics:");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"TSO pkts %lld, bytes %lld\n",
pdev->stats.pub.tx.tso.tso_pkts.pkts,
pdev->stats.pub.tx.tso.tso_pkts.bytes);
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ "TSO Histogram for numbers of segments:\n"
+ "Single segment %d\n"
+ " 2-5 segments %d\n"
+ " 6-10 segments %d\n"
+ "11-15 segments %d\n"
+ "16-20 segments %d\n"
+ " 20+ segments %d\n",
+ pdev->stats.pub.tx.tso.tso_hist.pkts_1,
+ pdev->stats.pub.tx.tso.tso_hist.pkts_2_5,
+ pdev->stats.pub.tx.tso.tso_hist.pkts_6_10,
+ pdev->stats.pub.tx.tso.tso_hist.pkts_11_15,
+ pdev->stats.pub.tx.tso.tso_hist.pkts_16_20,
+ pdev->stats.pub.tx.tso.tso_hist.pkts_20_plus);
+
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ "TSO History Buffer: Total size %d, current_index %d",
+ NUM_MAX_TSO_MSDUS,
+ TXRX_STATS_TSO_MSDU_IDX(pdev));
+
for (msdu_idx = 0; msdu_idx < NUM_MAX_TSO_MSDUS; msdu_idx++) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "curr msdu idx: %d curr seg idx: %d num segs %d\n",
- TXRX_STATS_TSO_MSDU_IDX(pdev),
- TXRX_STATS_TSO_SEG_IDX(pdev),
- TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, msdu_idx));
+ "jumbo pkt idx: %d num segs %d gso_len %d total_len %d nr_frags %d",
+ msdu_idx,
+ TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, msdu_idx),
+ TXRX_STATS_TSO_MSDU_GSO_SIZE(pdev, msdu_idx),
+ TXRX_STATS_TSO_MSDU_TOTAL_LEN(pdev, msdu_idx),
+ TXRX_STATS_TSO_MSDU_NR_FRAGS(pdev, msdu_idx));
+
for (seg_idx = 0;
((seg_idx < TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, msdu_idx)) &&
(seg_idx < NUM_MAX_TSO_SEGS));
@@ -3539,24 +3564,23 @@ void ol_txrx_stats_display_tso(ol_txrx_pdev_handle pdev)
TXRX_STATS_TSO_SEG(pdev, msdu_idx, seg_idx);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "msdu idx: %d seg idx: %d\n",
- msdu_idx, seg_idx);
+ "seg idx: %d", seg_idx);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "tso_enable: %d\n",
+ "tso_enable: %d",
tso_seg.tso_flags.tso_enable);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "fin %d syn %d rst %d psh %d ack %d\n"
- "urg %d ece %d cwr %d ns %d\n",
+ "fin %d syn %d rst %d psh %d ack %d urg %d ece %d cwr %d ns %d",
tso_seg.tso_flags.fin, tso_seg.tso_flags.syn,
tso_seg.tso_flags.rst, tso_seg.tso_flags.psh,
tso_seg.tso_flags.ack, tso_seg.tso_flags.urg,
tso_seg.tso_flags.ece, tso_seg.tso_flags.cwr,
tso_seg.tso_flags.ns);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "tcp_seq_num: 0x%x ip_id: %d\n",
+ "tcp_seq_num: 0x%x ip_id: %d",
tso_seg.tso_flags.tcp_seq_num,
tso_seg.tso_flags.ip_id);
}
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "\n");
}
}
#else
@@ -3605,9 +3629,9 @@ void ol_txrx_stats_display(ol_txrx_pdev_handle pdev)
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"TX PATH Statistics:");
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "sent %lld msdus (%lld B), rejected %lld (%lld B), dropped %lld (%lld B)",
- pdev->stats.pub.tx.delivered.pkts,
- pdev->stats.pub.tx.delivered.bytes,
+ "sent %lld msdus (%lld B), host rejected %lld (%lld B), dropped %lld (%lld B)",
+ pdev->stats.pub.tx.from_stack.pkts,
+ pdev->stats.pub.tx.from_stack.bytes,
pdev->stats.pub.tx.dropped.host_reject.pkts,
pdev->stats.pub.tx.dropped.host_reject.bytes,
pdev->stats.pub.tx.dropped.download_fail.pkts
@@ -3617,9 +3641,12 @@ void ol_txrx_stats_display(ol_txrx_pdev_handle pdev)
+ pdev->stats.pub.tx.dropped.target_discard.bytes
+ pdev->stats.pub.tx.dropped.no_ack.bytes);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- " download fail: %lld (%lld B), "
+ "successfully delivered: %lld (%lld B), "
+ "download fail: %lld (%lld B), "
"target discard: %lld (%lld B), "
"no ack: %lld (%lld B)",
+ pdev->stats.pub.tx.delivered.pkts,
+ pdev->stats.pub.tx.delivered.bytes,
pdev->stats.pub.tx.dropped.download_fail.pkts,
pdev->stats.pub.tx.dropped.download_fail.bytes,
pdev->stats.pub.tx.dropped.target_discard.pkts,
@@ -3627,7 +3654,7 @@ void ol_txrx_stats_display(ol_txrx_pdev_handle pdev)
pdev->stats.pub.tx.dropped.no_ack.pkts,
pdev->stats.pub.tx.dropped.no_ack.bytes);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "Tx completion per interrupt:\n"
+ "Tx completions per HTT message:\n"
"Single Packet %d\n"
" 2-10 Packets %d\n"
"11-20 Packets %d\n"
@@ -3644,11 +3671,13 @@ void ol_txrx_stats_display(ol_txrx_pdev_handle pdev)
pdev->stats.pub.tx.comp_histogram.pkts_41_50,
pdev->stats.pub.tx.comp_histogram.pkts_51_60,
pdev->stats.pub.tx.comp_histogram.pkts_61_plus);
+
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"RX PATH Statistics:");
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"%lld ppdus, %lld mpdus, %lld msdus, %lld bytes\n"
- "dropped: err %lld (%lld B), peer_invalid %lld (%lld B), mic_err %lld (%lld B)",
+ "dropped: err %lld (%lld B), peer_invalid %lld (%lld B), mic_err %lld (%lld B)\n"
+ "msdus with frag_ind: %d msdus with offload_ind: %d",
pdev->stats.priv.rx.normal.ppdus,
pdev->stats.priv.rx.normal.mpdus,
pdev->stats.pub.rx.delivered.pkts,
@@ -3658,8 +3687,9 @@ void ol_txrx_stats_display(ol_txrx_pdev_handle pdev)
pdev->stats.pub.rx.dropped_peer_invalid.pkts,
pdev->stats.pub.rx.dropped_peer_invalid.bytes,
pdev->stats.pub.rx.dropped_mic_err.pkts,
- pdev->stats.pub.rx.dropped_mic_err.bytes);
-
+ pdev->stats.pub.rx.dropped_mic_err.bytes,
+ pdev->stats.pub.rx.msdus_with_frag_ind,
+ pdev->stats.pub.rx.msdus_with_offload_ind);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
" fwd to stack %d, fwd to fw %d, fwd to stack & fw %d\n",
@@ -3668,7 +3698,7 @@ void ol_txrx_stats_display(ol_txrx_pdev_handle pdev)
pdev->stats.pub.rx.intra_bss_fwd.packets_stack_n_fwd);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "rx packets per HTT indication:\n"
+ "Rx packets per HTT message:\n"
"Single Packet %d\n"
" 2-10 Packets %d\n"
"11-20 Packets %d\n"
@@ -4086,6 +4116,36 @@ void ol_txrx_ipa_uc_get_stat(ol_txrx_pdev_handle pdev)
}
#endif /* IPA_UC_OFFLOAD */
+/**
+ * ol_txrx_display_stats_help() - print statistics help
+ *
+ * Return: none
+ */
+static void ol_txrx_display_stats_help(void)
+{
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ "iwpriv wlan0 dumpStats [option] - dump statistics");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ "iwpriv wlan0 clearStats [option] - clear statistics");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ "options:");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ " 1 -- TXRX Layer statistics");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ " 2 -- Bandwidth compute timer stats");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ " 3 -- TSO statistics");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ " 4 -- Network queue statistics");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ " 5 -- Flow control statistics");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ " 6 -- Per Layer statistics");
+ QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+ " 7 -- Copy engine interrupt statistics");
+
+}
+
void ol_txrx_display_stats(uint16_t value)
{
ol_txrx_pdev_handle pdev;
@@ -4131,8 +4191,7 @@ void ol_txrx_display_stats(uint16_t value)
#endif
#endif
default:
- QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "%s: Unknown value", __func__);
+ ol_txrx_display_stats_help();
break;
}
}
@@ -4175,8 +4234,7 @@ void ol_txrx_clear_stats(uint16_t value)
break;
#endif
default:
- QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
- "%s: Unknown value", __func__);
+ ol_txrx_display_stats_help();
break;
}
}
diff --git a/core/dp/txrx/ol_txrx_flow_control.c b/core/dp/txrx/ol_txrx_flow_control.c
index 920f825f1ef5..fff6b114bfb1 100644
--- a/core/dp/txrx/ol_txrx_flow_control.c
+++ b/core/dp/txrx/ol_txrx_flow_control.c
@@ -156,22 +156,18 @@ void ol_tx_dump_flow_pool_info(void)
struct ol_tx_flow_pool_t tmp_pool;
- TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Global Pool\n");
- TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Total %d :: Available %d\n",
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Global Pool");
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Total %d :: Available %d",
pdev->tx_desc.pool_size, pdev->tx_desc.num_free);
- TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Invalid flow_pool %d\n",
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "Invalid flow_pool %d",
pdev->tx_desc.num_invalid_bin);
-
- TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "No of pool map received %d\n",
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "No of pool map received %d",
pdev->pool_stats.pool_map_count);
- TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "No of pool unmap received %d\n",
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "No of pool unmap received %d",
pdev->pool_stats.pool_unmap_count);
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
- "Pkt dropped due to unavailablity of pool %d\n",
+ "Pkt dropped due to unavailablity of pool %d",
pdev->pool_stats.pkt_drop_no_pool);
- TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
- "Pkt dropped due to unavailablity of descriptors %d\n",
- pdev->pool_stats.pkt_drop_no_desc);
/*
* Nested spin lock.
@@ -185,19 +181,23 @@ void ol_tx_dump_flow_pool_info(void)
qdf_mem_copy(&tmp_pool, pool, sizeof(tmp_pool));
qdf_spin_unlock_bh(&pool->flow_pool_lock);
qdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock);
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, "\n");
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
- "Flow_pool_id %d :: status %d\n",
+ "Flow_pool_id %d :: status %d",
tmp_pool.flow_pool_id, tmp_pool.status);
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
- "Total %d :: Available %d :: Deficient %d\n",
+ "Total %d :: Available %d :: Deficient %d",
tmp_pool.flow_pool_size, tmp_pool.avail_desc,
tmp_pool.deficient_desc);
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
- "Start_TH %d :: Stop_TH %d\n",
+ "Start threshold %d :: Stop threshold %d",
tmp_pool.start_th, tmp_pool.stop_th);
TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
- "Member flow_id %d :: flow_type %d\n",
+ "Member flow_id %d :: flow_type %d",
tmp_pool.member_flow_id, tmp_pool.flow_type);
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
+ "Pkt dropped due to unavailablity of descriptors %d",
+ tmp_pool.pkt_drop_no_desc);
qdf_spin_lock_bh(&pdev->tx_desc.flow_pool_list_lock);
}
qdf_spin_unlock_bh(&pdev->tx_desc.flow_pool_list_lock);
diff --git a/core/dp/txrx/ol_txrx_internal.h b/core/dp/txrx/ol_txrx_internal.h
index e84632201042..cb7368124328 100644
--- a/core/dp/txrx/ol_txrx_internal.h
+++ b/core/dp/txrx/ol_txrx_internal.h
@@ -689,6 +689,28 @@ NOT_IP_TCP:
#endif
#if defined(FEATURE_TSO_DEBUG)
+#define TXRX_STATS_TSO_HISTOGRAM(_pdev, _p_cntrs) \
+ do { \
+ if (_p_cntrs == 1) { \
+ TXRX_STATS_ADD(_pdev, pub.tx.tso.tso_hist.pkts_1, 1); \
+ } else if (_p_cntrs > 2 && _p_cntrs <= 5) { \
+ TXRX_STATS_ADD(_pdev, \
+ pub.tx.tso.tso_hist.pkts_2_5, 1); \
+ } else if (_p_cntrs > 5 && _p_cntrs <= 10) { \
+ TXRX_STATS_ADD(_pdev, \
+ pub.tx.tso.tso_hist.pkts_6_10, 1); \
+ } else if (_p_cntrs > 10 && _p_cntrs <= 15) { \
+ TXRX_STATS_ADD(_pdev, \
+ pub.tx.tso.tso_hist.pkts_11_15, 1); \
+ } else if (_p_cntrs > 15 && _p_cntrs <= 20) { \
+ TXRX_STATS_ADD(_pdev, \
+ pub.tx.tso.tso_hist.pkts_16_20, 1); \
+ } else if (_p_cntrs > 20) { \
+ TXRX_STATS_ADD(_pdev, \
+ pub.tx.tso.tso_hist.pkts_20_plus, 1); \
+ } \
+ } while (0)
+
#define TXRX_STATS_TSO_RESET_MSDU(pdev) \
do { \
int idx = TXRX_STATS_TSO_MSDU_IDX(pdev);\
@@ -705,6 +727,15 @@ NOT_IP_TCP:
#define TXRX_STATS_TSO_MSDU_NUM_SEG(pdev, idx) \
pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx].num_seg
+#define TXRX_STATS_TSO_MSDU_GSO_SIZE(pdev, idx) \
+ pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx].gso_size
+
+#define TXRX_STATS_TSO_MSDU_TOTAL_LEN(pdev, idx) \
+ pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx].total_len
+
+#define TXRX_STATS_TSO_MSDU_NR_FRAGS(pdev, idx) \
+ pdev->stats.pub.tx.tso.tso_info.tso_msdu_info[idx].nr_frags
+
#define TXRX_STATS_TSO_CURR_MSDU(pdev) \
TXRX_STATS_TSO_MSDU(pdev, TXRX_STATS_TSO_MSDU_IDX(pdev))
@@ -718,7 +749,11 @@ NOT_IP_TCP:
TXRX_STATS_TSO_CURR_MSDU(pdev).tso_seg_idx
#define TXRX_STATS_TSO_INC_SEG(pdev) \
- TXRX_STATS_TSO_CURR_MSDU(pdev).num_seg++
+ do { \
+ TXRX_STATS_TSO_CURR_MSDU(pdev).num_seg++; \
+ TXRX_STATS_TSO_CURR_MSDU(pdev).num_seg &= \
+ NUM_MAX_TSO_SEGS_MASK; \
+ } while (0)
#define TXRX_STATS_TSO_RST_SEG(pdev) \
TXRX_STATS_TSO_CURR_MSDU(pdev).num_seg = 0
@@ -742,7 +777,17 @@ NOT_IP_TCP:
#define TXRX_STATS_TSO_SEG_UPDATE(pdev, tso_seg) \
(TXRX_STATS_TSO_CURR_SEG(pdev) = tso_seg)
+#define TXRX_STATS_TSO_GSO_SIZE_UPDATE(pdev, size) \
+ (TXRX_STATS_TSO_CURR_MSDU(pdev).gso_size = size)
+
+#define TXRX_STATS_TSO_TOTAL_LEN_UPDATE(pdev, len) \
+ (TXRX_STATS_TSO_CURR_MSDU(pdev).total_len = len)
+
+#define TXRX_STATS_TSO_NUM_FRAGS_UPDATE(pdev, frags) \
+ (TXRX_STATS_TSO_CURR_MSDU(pdev).nr_frags = frags)
+
#else
+#define TXRX_STATS_TSO_HISTOGRAM(_pdev, _p_cntrs) /* no-op */
#define TXRX_STATS_TSO_RESET_MSDU(pdev) /* no-op */
#define TXRX_STATS_TSO_MSDU_IDX(pdev) /* no-op */
#define TXRX_STATS_TSO_MSDU(pdev, idx) /* no-op */
@@ -757,6 +802,12 @@ NOT_IP_TCP:
#define TXRX_STATS_TSO_INC_SEG(pdev) /* no-op */
#define TXRX_STATS_TSO_RST_SEG(pdev) /* no-op */
#define TXRX_STATS_TSO_RST_SEG_IDX(pdev) /* no-op */
+#define TXRX_STATS_TSO_GSO_SIZE_UPDATE(pdev, size) /* no-op */
+#define TXRX_STATS_TSO_TOTAL_LEN_UPDATE(pdev, len) /* no-op */
+#define TXRX_STATS_TSO_NUM_FRAGS_UPDATE(pdev, frags) /* no-op */
+#define TXRX_STATS_TSO_MSDU_GSO_SIZE(pdev, idx) /* no-op */
+#define TXRX_STATS_TSO_MSDU_TOTAL_LEN(pdev, idx) /* no-op */
+#define TXRX_STATS_TSO_MSDU_NR_FRAGS(pdev, idx) /* no-op */
#endif /* FEATURE_TSO_DEBUG */
diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h
index 25cdcff4a80f..bc219d2e05d4 100644
--- a/core/dp/txrx/ol_txrx_types.h
+++ b/core/dp/txrx/ol_txrx_types.h
@@ -443,13 +443,11 @@ enum flow_pool_status {
* @pool_map_count: flow pool map received
* @pool_unmap_count: flow pool unmap received
* @pkt_drop_no_pool: packets dropped due to unavailablity of pool
- * @pkt_drop_no_desc: packets dropped due to unavailablity of descriptors
*/
struct ol_txrx_pool_stats {
uint16_t pool_map_count;
uint16_t pool_unmap_count;
uint16_t pkt_drop_no_pool;
- uint16_t pkt_drop_no_desc;
};
/**
@@ -466,6 +464,7 @@ struct ol_txrx_pool_stats {
* @stop_th: stop threshold
* @start_th: start threshold
* @freelist: tx descriptor freelist
+ * @pkt_drop_no_desc: drop due to no descriptors
*/
struct ol_tx_flow_pool_t {
TAILQ_ENTRY(ol_tx_flow_pool_t) flow_pool_list_elem;
@@ -480,6 +479,7 @@ struct ol_tx_flow_pool_t {
uint16_t stop_th;
uint16_t start_th;
union ol_tx_desc_list_elem_t *freelist;
+ uint16_t pkt_drop_no_desc;
};
#endif
diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index f0212b7476d3..367d702cd845 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -1119,6 +1119,27 @@ typedef enum {
#define CFG_VHT_ENABLE_2x2_CAP_FEATURE_MAX (1)
#define CFG_VHT_ENABLE_2x2_CAP_FEATURE_DEFAULT (0)
+/*
+ * NSS cfg bit definition.
+ * STA BIT[0:1]
+ * SAP BIT[2:3]
+ * P2P_GO BIT[4:5]
+ * P2P_CLIENT BIT[6:7]
+ * IBSS BIT[8:9]
+ * TDLS BIT[10:11]
+ * P2P_DEVICE BIT[12:13]
+ * OCB BIT[14:15]
+ */
+#define CFG_VDEV_TYPE_NSS_2G "gVdevTypeNss_2g"
+#define CFG_VDEV_TYPE_NSS_2G_MIN (0x5555)
+#define CFG_VDEV_TYPE_NSS_2G_MAX (0xAAAA)
+#define CFG_VDEV_TYPE_NSS_2G_DEFAULT (0xAAAA)
+
+#define CFG_VDEV_TYPE_NSS_5G "gVdevTypeNss_5g"
+#define CFG_VDEV_TYPE_NSS_5G_MIN (0x5555)
+#define CFG_VDEV_TYPE_NSS_5G_MAX (0xAAAA)
+#define CFG_VDEV_TYPE_NSS_5G_DEFAULT (0xAAAA)
+
#define CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE "gEnableMuBformee"
#define CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_MIN (0)
#define CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE_MAX (1)
@@ -3681,6 +3702,8 @@ struct hdd_config {
uint8_t vhtRxMCS2x2;
uint8_t vhtTxMCS2x2;
bool enable2x2;
+ uint32_t vdev_type_nss_2g;
+ uint32_t vdev_type_nss_5g;
bool txchainmask1x1;
bool rxchainmask1x1;
bool enableMuBformee;
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index aebcf8c3d769..c4df74ab4d6a 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -319,12 +319,6 @@ extern spinlock_t hdd_context_lock;
#define WLAN_SAP_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME 100
#define WLAN_HDD_TX_FLOW_CONTROL_MAX_24BAND_CH 14
-#define HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390
-#define HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390
-#define HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780
-#define HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780
-
-
#define NUM_TX_RX_HISTOGRAM 1024
#define NUM_TX_RX_HISTOGRAM_MASK (NUM_TX_RX_HISTOGRAM - 1)
@@ -805,6 +799,7 @@ typedef struct multicast_addr_list {
struct hdd_netif_queue_stats {
uint16_t pause_count;
uint16_t unpause_count;
+ qdf_time_t total_pause_time;
};
/**
@@ -1257,10 +1252,13 @@ struct hdd_context_s {
uint16_t connected_peer_count;
tdls_scan_context_t tdls_scan_ctxt;
/* Lock to avoid race condition during TDLS operations */
+ qdf_spinlock_t tdls_ct_spinlock;
struct mutex tdls_lock;
uint8_t tdls_off_channel;
uint16_t tdls_channel_offset;
int32_t tdls_fw_off_chan_mode;
+ bool enable_tdls_connection_tracker;
+ uint8_t tdls_external_peer_count;
#endif
void *hdd_ipa;
diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h
index 2d446b4fe504..7b770ac9e37a 100644
--- a/core/hdd/inc/wlan_hdd_tdls.h
+++ b/core/hdd/inc/wlan_hdd_tdls.h
@@ -63,8 +63,12 @@
#define TDLS_PEER_LIST_SIZE 256
+#define TDLS_CT_MAC_AGE_OUT_TIME (30*60*1000) /* Age out time is 30 mins */
+
#define EXTTDLS_EVENT_BUF_SIZE (4096)
+#define TDLS_CT_MAC_MAX_TABLE_SIZE 8
+
/**
* struct tdls_config_params_t - tdls config params
*
@@ -72,6 +76,7 @@
* @tx_period_t: tx period
* @tx_packet_n: tx packets number
* @discovery_tries_n: discovery tries
+ * @idle_timeout_t: idle traffic time out value
* @idle_packet_n: idle packet number
* @rssi_trigger_threshold: rssi trigger threshold
* @rssi_teardown_threshold: rssi tear down threshold
@@ -82,6 +87,7 @@ typedef struct {
uint32_t tx_period_t;
uint32_t tx_packet_n;
uint32_t discovery_tries_n;
+ uint32_t idle_timeout_t;
uint32_t idle_packet_n;
int32_t rssi_trigger_threshold;
int32_t rssi_teardown_threshold;
@@ -286,10 +292,24 @@ typedef struct {
struct _hddTdlsPeer_t;
/**
+ * struct tdls_ct_mac_table - connection tracker peer mac address table
+ * @mac_address: peer mac address
+ * @tx_packet_cnt: number of tx pkts
+ * @rx_packet_cnt: number of rx pkts
+ * @peer_timestamp_ms: time stamp of latest peer traffic
+ */
+struct tdls_ct_mac_table {
+ struct qdf_mac_addr mac_address;
+ uint32_t tx_packet_cnt;
+ uint32_t rx_packet_cnt;
+ uint32_t peer_timestamp_ms;
+};
+/**
* struct tdlsCtx_t - tdls context
*
* @peer_list: peer list
* @pAdapter: pointer to adapter
+ * @peer_update_timer: connection tracker timer
* @peerDiscoverTimer: peer discovery timer
* @peerDiscoveryTimeoutTimer: peer discovery timeout timer
* @threshold_config: threshold config
@@ -298,12 +318,15 @@ struct _hddTdlsPeer_t;
* @ap_rssi: ap rssi
* @curr_candidate: current candidate
* @implicit_setup: implicit setup work queue
+ * @ct_peer_mac_table: linear mac address table for counting the packets
+ * @valid_mac_entries: number of valid mac entry in @ct_peer_mac_table
* @magic: magic
*
*/
typedef struct {
struct list_head peer_list[TDLS_PEER_LIST_SIZE];
hdd_adapter_t *pAdapter;
+ qdf_mc_timer_t peer_update_timer;
qdf_mc_timer_t peerDiscoveryTimeoutTimer;
tdls_config_params_t threshold_config;
int32_t discovery_peer_cnt;
@@ -311,6 +334,8 @@ typedef struct {
int8_t ap_rssi;
struct _hddTdlsPeer_t *curr_candidate;
struct work_struct implicit_setup;
+ struct tdls_ct_mac_table ct_peer_mac_table[TDLS_CT_MAC_MAX_TABLE_SIZE];
+ uint8_t valid_mac_entries;
uint32_t magic;
} tdlsCtx_t;
@@ -342,6 +367,8 @@ typedef struct {
* @op_class_for_pref_off_chan: op class for preferred off channel
* @pref_off_chan_num: preferred off channel number
* @op_class_for_pref_off_chan_is_set: op class for preferred off channel set
+ * @peer_idle_timer: time to check idle traffic in tdls peers
+ * @is_peer_idle_timer_initialised: Flag to check idle timer init
* @reason: reason
* @state_change_notification: state change notification
*/
@@ -371,6 +398,8 @@ typedef struct _hddTdlsPeer_t {
uint8_t op_class_for_pref_off_chan;
uint8_t pref_off_chan_num;
uint8_t op_class_for_pref_off_chan_is_set;
+ qdf_mc_timer_t peer_idle_timer;
+ bool is_peer_idle_timer_initialised;
tTDLSLinkReason reason;
cfg80211_exttdls_callback state_change_notification;
} hddTdlsPeer_t;
@@ -451,14 +480,16 @@ int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter,
tCsrTdlsLinkEstablishParams *
tdlsLinkEstablishParams);
hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter,
- const uint8_t *mac);
+ const uint8_t *mac,
+ bool need_mutex_lock);
int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, const uint8_t *mac,
tTDLSCapType cap);
void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer,
tTDLSLinkStatus status,
- tTDLSLinkReason reason);
+ tTDLSLinkReason reason,
+ bool lock_needed);
void wlan_hdd_tdls_set_link_status(hdd_adapter_t *pAdapter,
const uint8_t *mac,
tTDLSLinkStatus linkStatus,
@@ -503,7 +534,8 @@ void wlan_hdd_tdls_tncrement_peer_count(hdd_adapter_t *pAdapter);
void wlan_hdd_tdls_decrement_peer_count(hdd_adapter_t *pAdapter);
hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx,
- const uint8_t *mac, uint8_t skip_self);
+ const uint8_t *mac, uint8_t skip_self,
+ bool need_lock);
int wlan_hdd_tdls_copy_scan_context(hdd_context_t *pHddCtx,
struct wiphy *wiphy,
@@ -630,10 +662,13 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_first_connected_peer(hdd_adapter_t *adapter);
int hdd_set_tdls_offchannel(hdd_context_t *hdd_ctx, int offchannel);
int hdd_set_tdls_secoffchanneloffset(hdd_context_t *hdd_ctx, int offchanoffset);
int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode);
+void wlan_hdd_tdls_update_tx_pkt_cnt(hdd_adapter_t *adapter,
+ struct sk_buff *skb);
+void wlan_hdd_tdls_update_rx_pkt_cnt(hdd_adapter_t *adapter,
+ struct sk_buff *skb);
int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val);
void hdd_tdls_context_init(hdd_context_t *hdd_ctx);
void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx);
-
#else
static inline void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter,
hdd_context_t *hddctx)
@@ -646,7 +681,14 @@ wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx)
static inline void wlan_hdd_tdls_exit(hdd_adapter_t *adapter)
{
}
-
+static inline void wlan_hdd_tdls_update_tx_pkt_cnt(hdd_adapter_t *adapter,
+ struct sk_buff *skb)
+{
+}
+static inline void wlan_hdd_tdls_update_rx_pkt_cnt(hdd_adapter_t *adapter,
+ struct sk_buff *skb)
+{
+}
static inline void hdd_tdls_context_init(hdd_context_t *hdd_ctx) { }
static inline void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx) { }
#endif /* End of FEATURE_WLAN_TDLS */
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index 85debbd99df0..28a98c5db86e 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -1066,7 +1066,7 @@ static QDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter,
/* HDD has initiated disconnect, do not send disconnect indication
* to kernel. Sending disconnected event to kernel for userspace
- * initiated disconnect will be handled by hdd_DisConnectHandler call
+ * initiated disconnect will be handled by disconnect handler call
* to cfg80211_disconnected.
*/
if ((eConnectionState_Disconnecting ==
@@ -1104,19 +1104,14 @@ static QDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter,
if (pRoamInfo->reasonCode ==
eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON)
pr_info("wlan: disconnected due to poor signal, rssi is %d dB\n", pRoamInfo->rxRssi);
- cfg80211_disconnected(dev, pRoamInfo->
- reasonCode, NULL, 0,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
- true,
-#endif
- GFP_KERNEL);
+ wlan_hdd_cfg80211_indicate_disconnect(
+ dev, false,
+ pRoamInfo->reasonCode);
} else {
- cfg80211_disconnected(dev,
- WLAN_REASON_UNSPECIFIED, NULL, 0,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
- true,
-#endif
- GFP_KERNEL);
+ wlan_hdd_cfg80211_indicate_disconnect(
+ dev, false,
+ WLAN_REASON_UNSPECIFIED
+ );
}
hdd_info("sent disconnected event to nl80211, rssi: %d",
@@ -3315,7 +3310,8 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter,
curr_peer =
wlan_hdd_tdls_get_peer(pAdapter,
- pRoamInfo->peerMac.bytes);
+ pRoamInfo->peerMac.bytes,
+ true);
if (!curr_peer) {
hddLog(LOGE, FL("curr_peer is null"));
status = QDF_STATUS_E_FAILURE;
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index 137a719c1548..af43bf1f7df7 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -2094,6 +2094,20 @@ REG_TABLE_ENTRY g_registry_table[] = {
CFG_VHT_ENABLE_2x2_CAP_FEATURE_MIN,
CFG_VHT_ENABLE_2x2_CAP_FEATURE_MAX),
+ REG_VARIABLE(CFG_VDEV_TYPE_NSS_2G, WLAN_PARAM_Integer,
+ struct hdd_config, vdev_type_nss_2g,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_VDEV_TYPE_NSS_2G_DEFAULT,
+ CFG_VDEV_TYPE_NSS_2G_MIN,
+ CFG_VDEV_TYPE_NSS_2G_MAX),
+
+ REG_VARIABLE(CFG_VDEV_TYPE_NSS_5G, WLAN_PARAM_Integer,
+ struct hdd_config, vdev_type_nss_5g,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_VDEV_TYPE_NSS_5G_DEFAULT,
+ CFG_VDEV_TYPE_NSS_5G_MIN,
+ CFG_VDEV_TYPE_NSS_5G_MAX),
+
REG_VARIABLE(CFG_VHT_ENABLE_MU_BFORMEE_CAP_FEATURE, WLAN_PARAM_Integer,
struct hdd_config, enableMuBformee,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@@ -6478,48 +6492,6 @@ bool hdd_update_config_dat(hdd_context_t *pHddCtx)
if ((pConfig->dot11Mode == eHDD_DOT11_MODE_AUTO) ||
(pConfig->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
(pConfig->dot11Mode == eHDD_DOT11_MODE_11ac)) {
- uint32_t temp = 0;
-
- sme_cfg_get_int(pHddCtx->hHal,
- WNI_CFG_VHT_BASIC_MCS_SET, &temp);
- temp = (temp & 0xFFFC) | pConfig->vhtRxMCS;
- if (pConfig->enable2x2)
- temp = (temp & 0xFFF3) | (pConfig->vhtRxMCS2x2 << 2);
- if (sme_cfg_set_int(pHddCtx->hHal,
- WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
- QDF_STATUS_E_FAILURE) {
- fStatus = false;
- hddLog(LOGE,
- "Could not pass on WNI_CFG_VHT_BASIC_MCS_SET to CFG");
- }
-
- sme_cfg_get_int(pHddCtx->hHal, WNI_CFG_VHT_RX_MCS_MAP,
- &temp);
- temp = (temp & 0xFFFC) | pConfig->vhtRxMCS;
- if (pConfig->enable2x2)
- temp = (temp & 0xFFF3) | (pConfig->vhtRxMCS2x2 << 2);
- if (sme_cfg_set_int(pHddCtx->hHal,
- WNI_CFG_VHT_RX_MCS_MAP, temp)
- == QDF_STATUS_E_FAILURE) {
- fStatus = false;
- hddLog(LOGE,
- "Could not pass on WNI_CFG_VHT_RX_MCS_MAP to CFG");
- }
- sme_cfg_get_int(pHddCtx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
- temp = (temp & 0xFFFC) | pConfig->vhtTxMCS;
- if (pConfig->enable2x2)
- temp = (temp & 0xFFF3) | (pConfig->vhtTxMCS2x2 << 2);
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO_HIGH,
- "vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
- pConfig->vhtRxMCS2x2, temp,
- pConfig->enable2x2);
-
- if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_VHT_TX_MCS_MAP,
- temp) == QDF_STATUS_E_FAILURE) {
- fStatus = false;
- hddLog(LOGE,
- "Could not pass on WNI_CFG_VHT_TX_MCS_MAP to CFG");
- }
/* Currently shortGI40Mhz is used for shortGI80Mhz */
if (sme_cfg_set_int
(pHddCtx->hHal, WNI_CFG_VHT_SHORT_GI_80MHZ,
@@ -6542,9 +6514,9 @@ bool hdd_update_config_dat(hdd_context_t *pHddCtx)
/* Change MU Bformee only when TxBF is enabled */
if (pConfig->enableTxBF) {
sme_cfg_get_int(pHddCtx->hHal,
- WNI_CFG_VHT_MU_BEAMFORMEE_CAP, &temp);
+ WNI_CFG_VHT_MU_BEAMFORMEE_CAP, &val);
- if (temp != pConfig->enableMuBformee) {
+ if (val != pConfig->enableMuBformee) {
if (sme_cfg_set_int(pHddCtx->hHal,
WNI_CFG_VHT_MU_BEAMFORMEE_CAP,
pConfig->enableMuBformee
@@ -7299,12 +7271,12 @@ QDF_STATUS hdd_update_nss(hdd_context_t *hdd_ctx, uint8_t nss)
if (!hdd_config->enable2x2) {
/* 1x1 */
- rx_supp_data_rate = HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
- tx_supp_data_rate = HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
+ rx_supp_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
+ tx_supp_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
} else {
/* 2x2 */
- rx_supp_data_rate = HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
- tx_supp_data_rate = HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
+ rx_supp_data_rate = VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
+ tx_supp_data_rate = VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2;
}
/* Update Rx Highest Long GI data Rate */
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index fd05af138484..5f695e28a98a 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -4484,6 +4484,9 @@ static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
return -EINVAL;
}
+ if (0 != wlan_hdd_check_remain_on_channel(adapter))
+ hdd_warn("Remain On Channel Pending");
+
if (hdd_ctx->config->policy_manager_enabled) {
ret = qdf_reset_connection_update();
if (!QDF_IS_STATUS_SUCCESS(ret))
@@ -9896,11 +9899,8 @@ disconnected:
* is handled by __cfg80211_disconnect call to __cfg80211_disconnected
*/
hddLog(LOG1, FL("Send disconnected event to userspace"));
- cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, NULL, 0,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
- false,
-#endif
- GFP_KERNEL);
+ wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
+ WLAN_REASON_UNSPECIFIED);
#endif
return result;
@@ -12361,4 +12361,8 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
.channel_switch = wlan_hdd_cfg80211_channel_switch,
#endif
.set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
+ defined(CFG80211_ABORT_SCAN)
+ .abort_scan = wlan_hdd_cfg80211_abort_scan,
+#endif
};
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index c91fa417f92c..a3ab7485feb7 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -2551,4 +2551,23 @@ int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy,
void hdd_get_bpf_offload_cb(void *hdd_context, struct sir_bpf_get_offload *);
void hdd_init_bpf_completion(void);
+
+#if defined(CFG80211_DISCONNECTED_V2) || \
+(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
+static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev,
+ bool locally_generated,
+ int reason)
+{
+ cfg80211_disconnected(dev, reason, NULL, 0,
+ locally_generated, GFP_KERNEL);
+}
+#else
+static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev,
+ bool locally_generated,
+ int reason)
+{
+ cfg80211_disconnected(dev, reason, NULL, 0,
+ GFP_KERNEL);
+}
+#endif
#endif
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index bd2cda48baae..00b8365073ca 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -2202,6 +2202,10 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev,
value[1], value[2]);
if (value[1] == DUMP_DP_TRACE)
qdf_dp_trace_dump_all(value[2]);
+ else if (value[1] == ENABLE_DP_TRACE_LIVE_MODE)
+ qdf_dp_trace_enable_live_mode();
+ else if (value[1] == CLEAR_DP_TRACE_BUFFER)
+ qdf_dp_trace_clear_buffer();
break;
case QCSAP_ENABLE_FW_PROFILE:
hddLog(LOG1, "QCSAP_ENABLE_FW_PROFILE: %d %d",
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index c1ae84d90920..a9245e006903 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -816,6 +816,29 @@ static void hdd_update_tgt_services(hdd_context_t *hdd_ctx,
}
+/**
+ * hdd_update_vdev_nss() - sets the vdev nss
+ * @hdd_ctx: HDD context
+ *
+ * Sets the Nss per vdev type based on INI
+ *
+ * Return: None
+ */
+static void hdd_update_vdev_nss(hdd_context_t *hdd_ctx)
+{
+ struct hdd_config *cfg_ini = hdd_ctx->config;
+ uint8_t max_supp_nss = 1;
+
+ if (cfg_ini->enable2x2)
+ max_supp_nss = 2;
+
+ sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
+ cfg_ini->vdev_type_nss_2g, eCSR_BAND_24);
+
+ sme_update_vdev_type_nss(hdd_ctx->hHal, max_supp_nss,
+ cfg_ini->vdev_type_nss_5g, eCSR_BAND_5G);
+}
+
static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
struct wma_tgt_ht_cap *cfg)
{
@@ -888,7 +911,7 @@ static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
/* Update Rx Highest Long GI data Rate */
if (sme_cfg_set_int(hdd_ctx->hHal,
WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
- HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
+ VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1)
== QDF_STATUS_E_FAILURE) {
hddLog(LOGE,
FL(
@@ -900,12 +923,11 @@ static void hdd_update_tgt_ht_cap(hdd_context_t *hdd_ctx,
if (sme_cfg_set_int
(hdd_ctx->hHal,
WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
- HDD_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
+ VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1) ==
QDF_STATUS_E_FAILURE) {
hddLog(LOGE,
FL(
- "Could not pass on HDD_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 to CCM"
- ));
+ "VHT_TX_HIGHEST_SUPP_RATE_1_1 to CCM fail"));
}
}
if (!(cfg->ht_tx_stbc && pconfig->enable2x2))
@@ -950,6 +972,7 @@ static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
struct wiphy *wiphy = hdd_ctx->wiphy;
struct ieee80211_supported_band *band_5g =
wiphy->bands[IEEE80211_BAND_5GHZ];
+ uint32_t temp = 0;
/* Get the current MPDU length */
status =
@@ -988,9 +1011,41 @@ static void hdd_update_tgt_vht_cap(hdd_context_t *hdd_ctx,
value = 0;
}
+ sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, &temp);
+ temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
+
+ if (pconfig->enable2x2)
+ temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
+
+ if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_BASIC_MCS_SET, temp) ==
+ QDF_STATUS_E_FAILURE) {
+ hdd_err("Could not pass VHT_BASIC_MCS_SET to CCM");
+ }
+
+ sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, &temp);
+ temp = (temp & VHT_MCS_1x1) | pconfig->vhtRxMCS;
+ if (pconfig->enable2x2)
+ temp = (temp & VHT_MCS_2x2) | (pconfig->vhtRxMCS2x2 << 2);
+
+ if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_RX_MCS_MAP, temp) ==
+ QDF_STATUS_E_FAILURE) {
+ hdd_err("Could not pass WNI_CFG_VHT_RX_MCS_MAP to CCM");
+ }
+
+ sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, &temp);
+ temp = (temp & VHT_MCS_1x1) | pconfig->vhtTxMCS;
+ if (pconfig->enable2x2)
+ temp = (temp & VHT_MCS_2x2) | (pconfig->vhtTxMCS2x2 << 2);
+
+ hdd_info("vhtRxMCS2x2 - %x temp - %u enable2x2 %d",
+ pconfig->vhtRxMCS2x2, temp, pconfig->enable2x2);
+
+ if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_VHT_TX_MCS_MAP, temp) ==
+ QDF_STATUS_E_FAILURE) {
+ hdd_err("Could not pass WNI_CFG_VHT_TX_MCS_MAP to CCM");
+ }
/* Get the current RX LDPC setting */
- status =
- sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
+ status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_VHT_LDPC_CODING_CAP,
&value);
if (status != QDF_STATUS_SUCCESS) {
@@ -1319,6 +1374,8 @@ void hdd_update_tgt_cfg(void *context, void *param)
hdd_ctx->ap_arpns_support = cfg->ap_arpns_support;
hdd_update_tgt_services(hdd_ctx, &cfg->services);
+ hdd_update_vdev_nss(hdd_ctx);
+
hdd_update_tgt_ht_cap(hdd_ctx, &cfg->ht_cap);
hdd_update_tgt_vht_cap(hdd_ctx, &cfg->vht_cap);
@@ -2164,6 +2221,7 @@ QDF_STATUS hdd_init_station_mode(hdd_adapter_t *adapter)
INIT_COMPLETION(adapter->session_open_comp_var);
sme_set_curr_device_mode(hdd_ctx->hHal, adapter->device_mode);
+ sme_set_pdev_ht_vht_ies(hdd_ctx->hHal, hdd_ctx->config->enable2x2);
status = cds_get_vdev_types(adapter->device_mode, &type, &subType);
if (QDF_STATUS_SUCCESS != status) {
hddLog(LOGE, FL("failed to get vdev type"));
@@ -3262,13 +3320,9 @@ QDF_STATUS hdd_start_all_adapters(hdd_context_t *hdd_ctx)
hdd_ReassocScenario = false;
/* indicate disconnected event to nl80211 */
- cfg80211_disconnected(adapter->dev,
- WLAN_REASON_UNSPECIFIED,
- NULL, 0,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || defined(WITH_BACKPORTS)
- true,
-#endif
- GFP_KERNEL);
+ wlan_hdd_cfg80211_indicate_disconnect(
+ adapter->dev, false,
+ WLAN_REASON_UNSPECIFIED);
} else if (eConnectionState_Connecting == connState) {
/*
* Indicate connect failure to supplicant if we were in the
@@ -4184,6 +4238,8 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx)
/* Proceed and complete the clean up */
}
+ wlansap_global_deinit();
+
free_hdd_ctx:
wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
@@ -4782,6 +4838,23 @@ void wlan_hdd_deinit_tx_rx_histogram(hdd_context_t *hdd_ctx)
}
}
+static uint8_t *convert_level_to_string(uint32_t level)
+{
+ switch (level) {
+ /* initialize the wlan sub system */
+ case WLAN_SVC_TP_NONE:
+ return "NONE";
+ case WLAN_SVC_TP_LOW:
+ return "LOW";
+ case WLAN_SVC_TP_MEDIUM:
+ return "MED";
+ case WLAN_SVC_TP_HIGH:
+ return "HIGH";
+ default:
+ return "INVAL";
+ }
+}
+
/**
* wlan_hdd_display_tx_rx_histogram() - display tx rx histogram
@@ -4794,32 +4867,42 @@ void wlan_hdd_display_tx_rx_histogram(hdd_context_t *hdd_ctx)
int i;
#ifdef MSM_PLATFORM
- hddLog(QDF_TRACE_LEVEL_ERROR, "BW Interval: %d curr_index %d",
- hdd_ctx->config->busBandwidthComputeInterval,
- hdd_ctx->hdd_txrx_hist_idx);
+ hddLog(QDF_TRACE_LEVEL_ERROR, "BW compute Interval: %dms",
+ hdd_ctx->config->busBandwidthComputeInterval);
hddLog(QDF_TRACE_LEVEL_ERROR,
"BW High TH: %d BW Med TH: %d BW Low TH: %d",
hdd_ctx->config->busBandwidthHighThreshold,
hdd_ctx->config->busBandwidthMediumThreshold,
hdd_ctx->config->busBandwidthLowThreshold);
+ hddLog(QDF_TRACE_LEVEL_ERROR, "Enable TCP DEL ACK: %d",
+ hdd_ctx->config->enable_tcp_delack);
hddLog(QDF_TRACE_LEVEL_ERROR, "TCP DEL High TH: %d TCP DEL Low TH: %d",
hdd_ctx->config->tcpDelackThresholdHigh,
hdd_ctx->config->tcpDelackThresholdLow);
+ hddLog(QDF_TRACE_LEVEL_ERROR,
+ "TCP TX HIGH TP TH: %d (Use to set tcp_output_bytes_limit)",
+ hdd_ctx->config->tcp_tx_high_tput_thres);
#endif
+ hddLog(QDF_TRACE_LEVEL_ERROR, "Total entries: %d Current index: %d",
+ NUM_TX_RX_HISTOGRAM, hdd_ctx->hdd_txrx_hist_idx);
+
hddLog(QDF_TRACE_LEVEL_ERROR,
- "index, total_rx, interval_rx, total_tx, interval_tx, next_vote_level, next_rx_level, next_tx_level");
+ "index, total_rx, interval_rx, total_tx, interval_tx, bus_bw_level, RX TP Level, TX TP Level");
for (i = 0; i < NUM_TX_RX_HISTOGRAM; i++) {
hddLog(QDF_TRACE_LEVEL_ERROR,
- "%d: %llu, %llu, %llu, %llu, %d, %d, %d",
+ "%d: %llu, %llu, %llu, %llu, %s, %s, %s",
i, hdd_ctx->hdd_txrx_hist[i].total_rx,
hdd_ctx->hdd_txrx_hist[i].interval_rx,
hdd_ctx->hdd_txrx_hist[i].total_tx,
hdd_ctx->hdd_txrx_hist[i].interval_tx,
- hdd_ctx->hdd_txrx_hist[i].next_vote_level,
- hdd_ctx->hdd_txrx_hist[i].next_rx_level,
- hdd_ctx->hdd_txrx_hist[i].next_tx_level);
+ convert_level_to_string(
+ hdd_ctx->hdd_txrx_hist[i].next_vote_level),
+ convert_level_to_string(
+ hdd_ctx->hdd_txrx_hist[i].next_rx_level),
+ convert_level_to_string(
+ hdd_ctx->hdd_txrx_hist[i].next_tx_level));
}
return;
}
@@ -4850,29 +4933,27 @@ void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
QDF_STATUS status;
int i;
- qdf_time_t total, pause, unpause, curr_time;
+ qdf_time_t total, pause, unpause, curr_time, delta;
status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
adapter = adapter_node->pAdapter;
hddLog(QDF_TRACE_LEVEL_ERROR,
+ "\nNetif queue operation statistics:");
+ hddLog(QDF_TRACE_LEVEL_ERROR,
"Session_id %d device mode %d",
adapter->sessionId, adapter->device_mode);
-
- hddLog(QDF_TRACE_LEVEL_ERROR,
- "Netif queue operation statistics:");
hddLog(QDF_TRACE_LEVEL_ERROR,
"Current pause_map value %x", adapter->pause_map);
curr_time = qdf_system_ticks();
total = curr_time - adapter->start_time;
+ delta = curr_time - adapter->last_time;
if (adapter->pause_map) {
- pause = adapter->total_pause_time +
- curr_time - adapter->last_time;
+ pause = adapter->total_pause_time + delta;
unpause = adapter->total_unpause_time;
} else {
- unpause = adapter->total_unpause_time +
- curr_time - adapter->last_time;
+ unpause = adapter->total_unpause_time + delta;
pause = adapter->total_pause_time;
}
hddLog(QDF_TRACE_LEVEL_ERROR,
@@ -4881,19 +4962,30 @@ void wlan_hdd_display_netif_queue_history(hdd_context_t *hdd_ctx)
qdf_system_ticks_to_msecs(pause),
qdf_system_ticks_to_msecs(unpause));
hddLog(QDF_TRACE_LEVEL_ERROR,
- "reason_type: pause_cnt: unpause_cnt");
+ "reason_type: pause_cnt: unpause_cnt: pause_time");
+
+ for (i = WLAN_CONTROL_PATH; i < WLAN_REASON_TYPE_MAX; i++) {
+ qdf_time_t pause_delta = 0;
+
+ if (adapter->pause_map & (1 << i))
+ pause_delta = delta;
- for (i = 1; i < WLAN_REASON_TYPE_MAX; i++) {
hddLog(QDF_TRACE_LEVEL_ERROR,
- "%s: %d: %d",
+ "%s: %d: %d: %ums",
hdd_reason_type_to_string(i),
adapter->queue_oper_stats[i].pause_count,
- adapter->queue_oper_stats[i].unpause_count);
+ adapter->queue_oper_stats[i].unpause_count,
+ qdf_system_ticks_to_msecs(
+ adapter->queue_oper_stats[i].total_pause_time +
+ pause_delta));
}
hddLog(QDF_TRACE_LEVEL_ERROR,
- "Netif queue operation history: current index %d",
- adapter->history_index);
+ "\nNetif queue operation history:");
+ hddLog(QDF_TRACE_LEVEL_ERROR,
+ "Total entries: %d current index %d",
+ WLAN_HDD_MAX_HISTORY_ENTRY, adapter->history_index);
+
hddLog(QDF_TRACE_LEVEL_ERROR,
"index: time: action_type: reason_type: pause_map");
@@ -6590,13 +6682,17 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx);
if (status != QDF_STATUS_SUCCESS) {
hdd_err("Failed to disable dual mac features");
- goto err_exit_nl_srv;
+ goto err_debugfs_exit;
}
}
ret = hdd_register_notifiers(hdd_ctx);
if (ret)
- goto err_exit_nl_srv;
+ goto err_debugfs_exit;
+
+ status = wlansap_global_init();
+ if (QDF_IS_STATUS_ERROR(status))
+ goto err_debugfs_exit;
memdump_init();
diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c
index 21756643bc8a..598c3d33b4d7 100644
--- a/core/hdd/src/wlan_hdd_power.c
+++ b/core/hdd/src/wlan_hdd_power.c
@@ -1442,6 +1442,8 @@ QDF_STATUS hdd_wlan_shutdown(void)
so setting it to NULL in hdd context */
pHddCtx->hHal = (tHalHandle) NULL;
+ wlansap_global_deinit();
+
hddLog(QDF_TRACE_LEVEL_FATAL, "%s: WLAN driver shutdown complete",
__func__);
return QDF_STATUS_SUCCESS;
@@ -1664,6 +1666,7 @@ QDF_STATUS hdd_wlan_re_init(void *hif_sc)
pHddCtx->target_hw_version,
pHddCtx->target_hw_name);
#endif
+ wlansap_global_init();
hddLog(LOGE,
"%s: WLAN host driver reinitiation completed!", __func__);
diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c
index 7e3acd7d3e84..484a78c562b6 100644
--- a/core/hdd/src/wlan_hdd_scan.c
+++ b/core/hdd/src/wlan_hdd_scan.c
@@ -1923,13 +1923,13 @@ int wlan_hdd_cfg80211_vendor_scan(struct wiphy *wiphy,
return ret;
}
+
/**
* wlan_hdd_scan_abort() - abort ongoing scan
* @pAdapter: Pointer to interface adapter
*
* Return: 0 for success, non zero for failure
*/
-#ifdef FEATURE_WLAN_SCAN_PNO
int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
@@ -1955,6 +1955,7 @@ int wlan_hdd_scan_abort(hdd_adapter_t *pAdapter)
return 0;
}
+#ifdef FEATURE_WLAN_SCAN_PNO
/**
* hdd_sched_scan_callback - scheduled scan callback
* @callbackContext: Callback context
@@ -2439,6 +2440,60 @@ int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
}
#endif /*FEATURE_WLAN_SCAN_PNO */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
+ defined(CFG80211_ABORT_SCAN)
+/**
+ * __wlan_hdd_cfg80211_abort_scan() - cfg80211 abort scan api
+ * @wiphy: Pointer to wiphy
+ * @wdev: Pointer to wireless device structure
+ *
+ * This function is used to abort an ongoing scan
+ *
+ * Return: None
+ */
+static void __wlan_hdd_cfg80211_abort_scan(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ int ret;
+
+ ENTER_DEV(dev);
+
+ if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+ hdd_err("Command not allowed in FTM mode");
+ return;
+ }
+
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (!ret)
+ return;
+
+ wlan_hdd_scan_abort(adapter);
+
+ EXIT();
+}
+
+/**
+ * wlan_hdd_cfg80211_abort_scan - cfg80211 abort scan api
+ * @wiphy: Pointer to wiphy
+ * @wdev: Pointer to wireless device structure
+ *
+ * Wrapper to __wlan_hdd_cfg80211_abort_scan() -
+ * function is used to abort an ongoing scan
+ *
+ * Return: None
+ */
+void wlan_hdd_cfg80211_abort_scan(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ cds_ssr_protect(__func__);
+ __wlan_hdd_cfg80211_abort_scan(wiphy, wdev);
+ cds_ssr_unprotect(__func__);
+}
+#endif
+
/**
* hdd_cleanup_scan_queue() - remove entries in scan queue
*
diff --git a/core/hdd/src/wlan_hdd_scan.h b/core/hdd/src/wlan_hdd_scan.h
index 50a6a8ddf273..3f8235dfa73d 100644
--- a/core/hdd/src/wlan_hdd_scan.h
+++ b/core/hdd/src/wlan_hdd_scan.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -71,5 +71,11 @@ int wlan_hdd_cfg80211_vendor_scan(struct wiphy *wiphy,
int data_len);
void hdd_cleanup_scan_queue(hdd_context_t *hdd_ctx);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
+ defined(CFG80211_ABORT_SCAN)
+void wlan_hdd_cfg80211_abort_scan(struct wiphy *wiphy,
+ struct wireless_dev *wdev);
+#endif
#endif /* end #if !defined(WLAN_HDD_SCAN_H) */
diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c
index 6d458c3b94b5..e1bb1e3dd9a1 100644
--- a/core/hdd/src/wlan_hdd_tdls.c
+++ b/core/hdd/src/wlan_hdd_tdls.c
@@ -44,12 +44,15 @@
#include "wlan_hdd_cfg80211.h"
#include "cds_sched.h"
#include "wma_types.h"
+#include "cds_concurrency.h"
+
static int32_t wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *
pHddTdlsCtx);
static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx);
int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac);
static void wlan_hdd_tdls_pre_setup(struct work_struct *work);
+static void wlan_hdd_tdls_ct_handler(void *user_data);
/*
* wlan_hdd_tdls_determine_channel_opclass() - determine channel and opclass
@@ -434,7 +437,8 @@ static void wlan_hdd_tdls_discovery_timeout_peer_cb(void *userData)
MAC_ADDR_ARRAY(tmp->peerMac));
wlan_hdd_tdls_set_peer_link_status(tmp,
eTDLS_LINK_IDLE,
- eTDLS_LINK_NOT_SUPPORTED);
+ eTDLS_LINK_NOT_SUPPORTED,
+ true);
mutex_lock(&pHddCtx->tdls_lock);
}
}
@@ -548,6 +552,42 @@ static void wlan_hdd_tdls_monitor_timers_stop(tdlsCtx_t *hdd_tdls_ctx)
}
/**
+ * wlan_hdd_tdls_peer_idle_timers_stop() - stop peer idle timers
+ * @hdd_tdls_ctx: TDLS context
+ *
+ * Loop through the idle peer list and stop their timers
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_peer_idle_timers_stop(tdlsCtx_t *hdd_tdls_ctx)
+{
+ int i;
+ struct list_head *head;
+ struct list_head *pos;
+ hddTdlsPeer_t *curr_peer;
+
+ for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) {
+ head = &hdd_tdls_ctx->peer_list[i];
+ list_for_each(pos, head) {
+ curr_peer = list_entry(pos, hddTdlsPeer_t, node);
+ qdf_mc_timer_stop(&curr_peer->peer_idle_timer);
+ }
+ }
+}
+
+/**
+ * wlan_hdd_tdls_ct_timers_stop() - stop tdls connection tracker timers
+ * @hdd_tdls_ctx: TDLS context
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_ct_timers_stop(tdlsCtx_t *hdd_tdls_ctx)
+{
+ qdf_mc_timer_stop(&hdd_tdls_ctx->peer_update_timer);
+ wlan_hdd_tdls_peer_idle_timers_stop(hdd_tdls_ctx);
+}
+
+/**
* wlan_hdd_tdls_timers_stop() - stop all the tdls timers running
* @hdd_tdls_ctx: TDLS context
*
@@ -556,6 +596,7 @@ static void wlan_hdd_tdls_monitor_timers_stop(tdlsCtx_t *hdd_tdls_ctx)
static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *hdd_tdls_ctx)
{
wlan_hdd_tdls_monitor_timers_stop(hdd_tdls_ctx);
+ wlan_hdd_tdls_ct_timers_stop(hdd_tdls_ctx);
}
/**
@@ -599,6 +640,7 @@ static void wlan_hdd_tdls_del_non_forced_peers(tdlsCtx_t *hdd_tdls_ctx)
void hdd_tdls_context_init(hdd_context_t *hdd_ctx)
{
mutex_init(&hdd_ctx->tdls_lock);
+ qdf_spinlock_create(&hdd_ctx->tdls_ct_spinlock);
}
/**
@@ -612,6 +654,7 @@ void hdd_tdls_context_init(hdd_context_t *hdd_ctx)
void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx)
{
mutex_destroy(&hdd_ctx->tdls_lock);
+ qdf_spinlock_destroy(&hdd_ctx->tdls_ct_spinlock);
}
/**
@@ -675,6 +718,11 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
/* initialize TDLS pAdater context */
qdf_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
+ /* Initialize connection tracker timer */
+ qdf_mc_timer_init(&pHddTdlsCtx->peer_update_timer,
+ QDF_TIMER_TYPE_SW,
+ wlan_hdd_tdls_ct_handler,
+ pAdapter);
qdf_mc_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer,
QDF_TIMER_TYPE_SW,
wlan_hdd_tdls_discovery_timeout_peer_cb,
@@ -702,6 +750,7 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
pHddCtx->tdls_scan_ctxt.attempt = 0;
pHddCtx->tdls_scan_ctxt.reject = 0;
pHddCtx->tdls_scan_ctxt.scan_request = NULL;
+ pHddCtx->tdls_external_peer_count = 0;
if (pHddCtx->config->fEnableTDLSSleepSta ||
pHddCtx->config->fEnableTDLSBufferSta ||
@@ -723,6 +772,12 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
pHddTdlsCtx->curr_candidate = NULL;
pHddTdlsCtx->magic = 0;
+ pHddTdlsCtx->valid_mac_entries = 0;
+
+ /* This flag will set be true, only when device operates in
+ * standalone STA mode
+ */
+ pHddCtx->enable_tdls_connection_tracker = false;
/* remember configuration even if it is not used right now. it could be used later */
pHddTdlsCtx->threshold_config.tx_period_t =
@@ -731,6 +786,8 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter)
pHddCtx->config->fTDLSTxPacketThreshold;
pHddTdlsCtx->threshold_config.discovery_tries_n =
pHddCtx->config->fTDLSMaxDiscoveryAttempt;
+ pHddTdlsCtx->threshold_config.idle_timeout_t =
+ pHddCtx->config->tdls_idle_timeout;
pHddTdlsCtx->threshold_config.idle_packet_n =
pHddCtx->config->fTDLSIdlePacketThreshold;
pHddTdlsCtx->threshold_config.rssi_trigger_threshold =
@@ -919,6 +976,7 @@ void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter)
}
pHddTdlsCtx->magic = 0;
+ pHddCtx->tdls_external_peer_count = 0;
pHddTdlsCtx->pAdapter = NULL;
qdf_mem_free(pHddTdlsCtx);
@@ -930,6 +988,46 @@ done:
}
/**
+ * wlan_hdd_tdls_peer_idle_timers_destroy() - destroy peer idle timers
+ * @hdd_tdls_ctx: TDLS context
+ *
+ * Loop through the idle peer list and destroy their timers
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_peer_idle_timers_destroy(tdlsCtx_t *hdd_tdls_ctx)
+{
+ int i;
+ struct list_head *head;
+ struct list_head *pos;
+ hddTdlsPeer_t *curr_peer;
+
+ for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) {
+ head = &hdd_tdls_ctx->peer_list[i];
+ list_for_each(pos, head) {
+ curr_peer = list_entry(pos, hddTdlsPeer_t, node);
+ hdd_info(MAC_ADDRESS_STR ": destroy idle timer",
+ MAC_ADDR_ARRAY(curr_peer->peerMac));
+ qdf_mc_timer_stop(&curr_peer->peer_idle_timer);
+ qdf_mc_timer_destroy(&curr_peer->peer_idle_timer);
+ }
+ }
+}
+
+/**
+ * wlan_hdd_tdls_ct_timers_destroy() - destroy tdls connection tracker timers
+ * @hdd_tdls_ctx: TDLS context
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_ct_timers_destroy(tdlsCtx_t *hdd_tdls_ctx)
+{
+ qdf_mc_timer_stop(&hdd_tdls_ctx->peer_update_timer);
+ qdf_mc_timer_destroy(&hdd_tdls_ctx->peer_update_timer);
+ wlan_hdd_tdls_peer_idle_timers_destroy(hdd_tdls_ctx);
+}
+
+/**
* wlan_hdd_tdls_monitor_timers_destroy() - destroy all tdls monitoring timers
* @pHddTdlsCtx: TDLS context
*
@@ -950,19 +1048,22 @@ static void wlan_hdd_tdls_monitor_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx)
{
wlan_hdd_tdls_monitor_timers_destroy(pHddTdlsCtx);
+ wlan_hdd_tdls_ct_timers_destroy(pHddTdlsCtx);
}
/**
* wlan_hdd_tdls_get_peer() - find or add an peer given mac address
* @pAdapter: HDD adapter
* @mac: MAC address used to find or create peer
+ * @need_mutex_lock: flag identify whether mutex needed or not
*
* Search peer given an MAC address and create one if not found.
*
* Return: Pointer to peer if mac address exist or peer creation
* succeeds; NULL if peer creation fails
*/
-hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac)
+hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac,
+ bool need_mutex_lock)
{
struct list_head *head;
hddTdlsPeer_t *peer;
@@ -974,7 +1075,7 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac)
return NULL;
/* if already there, just update */
- peer = wlan_hdd_tdls_find_peer(pAdapter, mac, true);
+ peer = wlan_hdd_tdls_find_peer(pAdapter, mac, need_mutex_lock);
if (peer != NULL) {
return peer;
}
@@ -987,13 +1088,15 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac)
return NULL;
}
- mutex_lock(&pHddCtx->tdls_lock);
+ if (need_mutex_lock)
+ mutex_lock(&pHddCtx->tdls_lock);
pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
if (NULL == pHddTdlsCtx) {
qdf_mem_free(peer);
- mutex_unlock(&pHddCtx->tdls_lock);
+ if (need_mutex_lock)
+ mutex_unlock(&pHddCtx->tdls_lock);
hddLog(LOG1, FL("pHddTdlsCtx is NULL"));
return NULL;
}
@@ -1010,7 +1113,9 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, const u8 *mac)
pHddCtx->config->fTDLSPrefOffChanBandwidth);
list_add_tail(&peer->node, head);
- mutex_unlock(&pHddCtx->tdls_lock);
+
+ if (need_mutex_lock)
+ mutex_unlock(&pHddCtx->tdls_lock);
return peer;
}
@@ -1028,7 +1133,7 @@ int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, const uint8_t *mac,
{
hddTdlsPeer_t *curr_peer;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1049,7 +1154,8 @@ int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, const uint8_t *mac,
*/
void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer,
tTDLSLinkStatus status,
- tTDLSLinkReason reason)
+ tTDLSLinkReason reason,
+ bool lock_needed)
{
uint32_t state = 0;
int32_t res = 0;
@@ -1072,7 +1178,9 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer,
"tdls set peer " MAC_ADDRESS_STR " link status to %u",
MAC_ADDR_ARRAY(curr_peer->peerMac), status);
- mutex_lock(&pHddCtx->tdls_lock);
+ if (lock_needed)
+ mutex_lock(&pHddCtx->tdls_lock);
+
curr_peer->link_status = status;
/* If TDLS link status is already passed the discovery state
@@ -1082,7 +1190,9 @@ void wlan_hdd_tdls_set_peer_link_status(hddTdlsPeer_t *curr_peer,
curr_peer->discovery_attempt = 0;
}
- mutex_unlock(&pHddCtx->tdls_lock);
+ if (lock_needed)
+ mutex_unlock(&pHddCtx->tdls_lock);
+
if (curr_peer->isForcedPeer && curr_peer->state_change_notification) {
uint32_t opclass;
uint32_t channel;
@@ -1184,7 +1294,7 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter,
if (0 != (wlan_hdd_validate_context(pHddCtx)))
return -EINVAL;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (NULL == curr_peer) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1214,7 +1324,8 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter,
rssi_trigger_threshold) {
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_DISCOVERED,
- eTDLS_LINK_SUCCESS);
+ eTDLS_LINK_SUCCESS,
+ true);
hddLog(LOG1,
"Rssi Threshold met: " MAC_ADDRESS_STR
" rssi = %d threshold= %d",
@@ -1236,7 +1347,8 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter,
rssi_trigger_threshold);
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_IDLE,
- eTDLS_LINK_UNSPECIFIED);
+ eTDLS_LINK_UNSPECIFIED,
+ true);
/* if RSSI threshold is not met then allow further discovery
* attempts by decrementing count for the last attempt
@@ -1268,7 +1380,7 @@ int wlan_hdd_tdls_set_peer_caps(hdd_adapter_t *pAdapter,
{
hddTdlsPeer_t *curr_peer;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1310,7 +1422,7 @@ int wlan_hdd_tdls_get_link_establish_params(hdd_adapter_t *pAdapter,
{
hddTdlsPeer_t *curr_peer;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1378,7 +1490,7 @@ int wlan_hdd_tdls_set_responder(hdd_adapter_t *pAdapter, const uint8_t *mac,
{
hddTdlsPeer_t *curr_peer;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1402,7 +1514,7 @@ int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, const uint8_t *mac,
{
hddTdlsPeer_t *curr_peer;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1414,18 +1526,6 @@ int wlan_hdd_tdls_set_signature(hdd_adapter_t *pAdapter, const uint8_t *mac,
}
/**
- * wlan_hdd_tdls_extract_da() - Extract destination address from socket buffer
- * @skb: socket buffer
- * @mac: output mac address buffer to store the destination address
- *
- * Return: Void
- */
-void wlan_hdd_tdls_extract_da(struct sk_buff *skb, uint8_t *mac)
-{
- memcpy(mac, skb->data, 6);
-}
-
-/**
* wlan_hdd_tdls_extract_sa() - Extract source address from socket buffer
* @skb: socket buffer
* @mac: output mac address buffer to store the source address
@@ -1455,7 +1555,7 @@ int wlan_hdd_tdls_increment_pkt_count(hdd_adapter_t *pAdapter,
eTDLS_SUPPORT_EXTERNAL_CONTROL != pHddCtx->tdls_mode)
return -EINVAL;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOG1, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1592,6 +1692,11 @@ static void wlan_hdd_tdls_implicit_enable(tdlsCtx_t *pHddTdlsCtx)
wlan_tdd_tdls_reset_tx_rx(pHddTdlsCtx);
wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
+ /* Restart the connection tracker timer */
+ wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
+ &pHddTdlsCtx->peer_update_timer,
+ pHddTdlsCtx->threshold_config.tx_period_t);
+
}
/**
@@ -1875,7 +1980,7 @@ int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, const uint8_t *mac,
{
hddTdlsPeer_t *curr_peer;
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -1999,7 +2104,6 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter,
tdlsCtx_t *pHddTdlsCtx;
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
- ENTER();
if (0 != (wlan_hdd_validate_context(pHddCtx)))
return NULL;
@@ -2031,7 +2135,7 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter,
}
if (mutexLock)
mutex_unlock(&pHddCtx->tdls_lock);
- EXIT();
+
return NULL;
}
@@ -2087,7 +2191,7 @@ int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const uint8_t *mac)
pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
- curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ curr_peer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (curr_peer == NULL) {
hddLog(LOGE, FL("curr_peer is NULL"));
return -EINVAL;
@@ -2111,7 +2215,8 @@ int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, const uint8_t *mac)
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_IDLE,
- eTDLS_LINK_UNSPECIFIED);
+ eTDLS_LINK_UNSPECIFIED,
+ true);
curr_peer->staId = 0;
return 0;
@@ -2240,6 +2345,7 @@ void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
{
tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter);
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+ uint32_t tx_period_t;
if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
@@ -2247,17 +2353,23 @@ void wlan_hdd_tdls_connection_callback(hdd_adapter_t *pAdapter)
return;
}
- mutex_lock(&pHddCtx->tdls_lock);
+ tx_period_t = pHddTdlsCtx->threshold_config.tx_period_t;
hddLog(LOG1,
FL("update %d"),
pHddTdlsCtx->threshold_config.tx_period_t);
+ mutex_lock(&pHddCtx->tdls_lock);
+
if (eTDLS_SUPPORT_ENABLED == pHddCtx->tdls_mode ||
eTDLS_SUPPORT_EXTERNAL_CONTROL == pHddCtx->tdls_mode) {
wlan_hdd_tdls_peer_reset_discovery_processed(pHddTdlsCtx);
pHddTdlsCtx->discovery_sent_cnt = 0;
wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
+ /* Start the connection tracker timer */
+ wlan_hdd_tdls_timer_restart(pHddTdlsCtx->pAdapter,
+ &pHddTdlsCtx->peer_update_timer,
+ tx_period_t);
}
mutex_unlock(&pHddCtx->tdls_lock);
@@ -2294,7 +2406,7 @@ void wlan_hdd_tdls_disconnection_callback(hdd_adapter_t *pAdapter)
pHddTdlsCtx->discovery_sent_cnt = 0;
wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter);
- wlan_hdd_tdls_monitor_timers_stop(pHddTdlsCtx);
+ wlan_hdd_tdls_timers_stop(pHddTdlsCtx);
wlan_hdd_tdls_free_list(pHddTdlsCtx);
pHddTdlsCtx->curr_candidate = NULL;
@@ -2431,11 +2543,14 @@ static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter,
* @pHddCtx: HDD context
* @mac: mac address of the peer
* @skip_self: if 1, skip checking self. If 0, search includes self
+ * @need_lock: flag to indicate, whether the caller acquired the mutex or not
*
* Return: TDLS peer if found; NULL otherwise
*/
hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx,
- const uint8_t *mac, uint8_t skip_self)
+ const uint8_t *mac,
+ uint8_t skip_self,
+ bool need_lock)
{
hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
hdd_adapter_t *pAdapter = NULL;
@@ -2443,7 +2558,8 @@ hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx,
hddTdlsPeer_t *curr_peer = NULL;
QDF_STATUS status = 0;
- mutex_lock(&pHddCtx->tdls_lock);
+ if (need_lock)
+ mutex_lock(&pHddCtx->tdls_lock);
status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
while (NULL != pAdapterNode && QDF_STATUS_SUCCESS == status) {
@@ -2455,14 +2571,18 @@ hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx,
wlan_hdd_tdls_find_progress_peer(pAdapter, mac,
skip_self);
if (curr_peer) {
- mutex_unlock(&pHddCtx->tdls_lock);
+ if (need_lock)
+ mutex_unlock(&pHddCtx->tdls_lock);
return curr_peer;
}
}
status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
pAdapterNode = pNext;
}
- mutex_unlock(&pHddCtx->tdls_lock);
+
+ if (need_lock)
+ mutex_unlock(&pHddCtx->tdls_lock);
+
return NULL;
}
@@ -2515,7 +2635,7 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work)
mutex_unlock(&pHddCtx->tdls_lock);
- temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
+ temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, true);
if (NULL != temp_peer) {
hddLog(LOG1,
@@ -2527,7 +2647,8 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work)
if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_DISCOVERING,
- eTDLS_LINK_SUCCESS);
+ eTDLS_LINK_SUCCESS,
+ true);
mutex_lock(&pHddCtx->tdls_lock);
@@ -2563,7 +2684,8 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work)
mutex_unlock(&pHddCtx->tdls_lock);
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_DISCOVERING,
- eTDLS_LINK_SUCCESS);
+ eTDLS_LINK_SUCCESS,
+ true);
status =
wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->
@@ -2589,7 +2711,8 @@ static void __wlan_hdd_tdls_pre_setup(struct work_struct *work)
mutex_unlock(&pHddCtx->tdls_lock);
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_IDLE,
- eTDLS_LINK_UNSPECIFIED);
+ eTDLS_LINK_UNSPECIFIED,
+ true);
mutex_lock(&pHddCtx->tdls_lock);
}
goto done;
@@ -2717,7 +2840,7 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy,
if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode)
return 1;
- curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0);
+ curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, true);
if (NULL != curr_peer) {
if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT) {
pHddCtx->tdls_scan_ctxt.reject = 0;
@@ -2729,7 +2852,8 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy,
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_IDLE,
- eTDLS_LINK_UNSPECIFIED);
+ eTDLS_LINK_UNSPECIFIED,
+ true);
return 1;
}
hddLog(LOGW,
@@ -2953,7 +3077,8 @@ void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter,
wlan_hdd_tdls_set_peer_link_status(curr_peer,
eTDLS_LINK_TEARING,
- eTDLS_LINK_UNSPECIFIED);
+ eTDLS_LINK_UNSPECIFIED,
+ true);
hdd_info("Teardown reason %d", reason);
cfg80211_tdls_oper_request(pAdapter->dev,
curr_peer->peerMac,
@@ -3531,7 +3656,7 @@ int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
return -ENOTSUPP;
}
- pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, mac);
+ pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, mac, true);
if (NULL == pTdlsPeer) {
hddLog(LOGE,
@@ -3567,7 +3692,7 @@ int wlan_hdd_tdls_add_station(struct wiphy *wiphy,
}
/* when others are on-going, we want to change link_status to idle */
- if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, true)) {
+ if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, true, true)) {
hddLog(LOG1,
"%s: " MAC_ADDRESS_STR
" TDLS setup is ongoing. Request declined.",
@@ -3821,7 +3946,8 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
}
if (WLAN_IS_TDLS_SETUP_ACTION(action_code)) {
- if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, true)) {
+ if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer,
+ true, true)) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
"%s: " MAC_ADDRESS_STR
" TDLS setup is ongoing. action %d declined.",
@@ -4118,7 +4244,7 @@ int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter,
__func__);
return -ENOTSUPP;
}
- pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer);
+ pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer, true);
if (pTdlsPeer == NULL) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
"%s: peer " MAC_ADDRESS_STR " does not exist",
@@ -4140,6 +4266,11 @@ int wlan_hdd_tdls_extctrl_config_peer(hdd_adapter_t *pAdapter,
return -EINVAL;
}
+ pHddCtx->tdls_external_peer_count++;
+
+ /* set tdls connection tracker state */
+ cds_set_tdls_ct_mode(pHddCtx);
+
/* validate if off channel is DFS channel */
if (CDS_IS_DFS_CH(chan)) {
hdd_err("Resetting TDLS off-channel from %d to %d",
@@ -4204,6 +4335,7 @@ int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter,
"%s Failed", __func__);
return -EINVAL;
}
+
/* Update the peer mac to firmware, so firmware
* could update the connection table
*/
@@ -4213,6 +4345,13 @@ int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter,
MAC_ADDR_ARRAY(peer));
return -EINVAL;
}
+
+ if (pHddCtx->tdls_external_peer_count)
+ pHddCtx->tdls_external_peer_count--;
+
+ /* set tdls connection tracker state */
+ cds_set_tdls_ct_mode(pHddCtx);
+
if (0 != wlan_hdd_set_callback(pTdlsPeer, NULL)) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
"%s TDLS set callback Failed", __func__);
@@ -4345,7 +4484,8 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
}
wlan_hdd_tdls_set_peer_link_status(pTdlsPeer,
eTDLS_LINK_CONNECTED,
- eTDLS_LINK_SUCCESS);
+ eTDLS_LINK_SUCCESS,
+ true);
/* start TDLS client registration with TL */
status =
hdd_roam_register_tdlssta(pAdapter, peer,
@@ -4558,7 +4698,8 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
(pTdlsPeer->link_status ==
eTDLS_LINK_TEARING) ?
eTDLS_LINK_UNSPECIFIED :
- eTDLS_LINK_DROPPED_BY_REMOTE);
+ eTDLS_LINK_DROPPED_BY_REMOTE,
+ true);
} else {
QDF_TRACE(QDF_MODULE_ID_HDD,
QDF_TRACE_LEVEL_ERROR,
@@ -4937,6 +5078,646 @@ int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode)
}
/**
+ * wlan_hdd_tdls_ct_sampling_tx_rx() - collect tx/rx traffic sample
+ * @adapter: pointer to hdd adapter
+ * @hdd_ctx: hdd context
+ * @tdls_ctx: tdls context
+ *
+ * Function to update data traffic information in tdls connection
+ * tracker data structure for connection tracker operation
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_ct_sampling_tx_rx(hdd_adapter_t *adapter,
+ hdd_context_t *hdd_ctx,
+ tdlsCtx_t *tdls_ctx)
+{
+ hddTdlsPeer_t *curr_peer;
+ uint8_t mac[QDF_MAC_ADDR_SIZE];
+ uint8_t mac_cnt;
+ uint8_t valid_mac_entries;
+ struct tdls_ct_mac_table ct_peer_mac_table[TDLS_CT_MAC_MAX_TABLE_SIZE];
+
+ qdf_spin_lock(&hdd_ctx->tdls_ct_spinlock);
+
+ if (0 == tdls_ctx->valid_mac_entries) {
+ qdf_spin_unlock(&hdd_ctx->tdls_ct_spinlock);
+ return;
+ }
+
+ valid_mac_entries = tdls_ctx->valid_mac_entries;
+
+ memcpy(ct_peer_mac_table, tdls_ctx->ct_peer_mac_table,
+ (sizeof(struct tdls_ct_mac_table)) * valid_mac_entries);
+
+ memset(tdls_ctx->ct_peer_mac_table, 0,
+ (sizeof(struct tdls_ct_mac_table)) * valid_mac_entries);
+
+ tdls_ctx->valid_mac_entries = 0;
+
+ qdf_spin_unlock(&hdd_ctx->tdls_ct_spinlock);
+
+ for (mac_cnt = 0; mac_cnt < valid_mac_entries; mac_cnt++) {
+ memcpy(mac, ct_peer_mac_table[mac_cnt].mac_address.bytes,
+ QDF_MAC_ADDR_SIZE);
+ curr_peer = wlan_hdd_tdls_get_peer(adapter, mac, false);
+ if (NULL != curr_peer) {
+ curr_peer->tx_pkt =
+ ct_peer_mac_table[mac_cnt].tx_packet_cnt;
+ curr_peer->rx_pkt =
+ ct_peer_mac_table[mac_cnt].rx_packet_cnt;
+ }
+ }
+}
+
+/**
+ * wlan_hdd_tdls_update_rx_pkt_cnt() - Update rx packet count
+ * @adapter: pointer to hdd adapter
+ * @skb: pointer to sk_buff
+ *
+ * Increase the rx packet count, if the sender is not bssid and the packet is
+ * not broadcast and muticast packet
+ *
+ * This sampling information will be used in TDLS connection tracker
+ *
+ * This function expected to be called in an atomic context so blocking APIs
+ * not allowed
+ *
+ * Return: None
+ */
+void wlan_hdd_tdls_update_rx_pkt_cnt(hdd_adapter_t *adapter,
+ struct sk_buff *skb)
+{
+ hdd_context_t *hdd_ctx;
+ hdd_station_ctx_t *hdd_sta_ctx;
+ tdlsCtx_t *tdls_ctx;
+ uint8_t mac_cnt;
+ uint8_t valid_mac_entries;
+ struct qdf_mac_addr *mac_addr;
+
+ mac_addr = (struct qdf_mac_addr *)(skb->data+QDF_MAC_ADDR_SIZE);
+ if (qdf_is_macaddr_group(mac_addr))
+ return;
+
+ hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (memcmp(hdd_sta_ctx->conn_info.bssId.bytes,
+ mac_addr, QDF_MAC_ADDR_SIZE) == 0)
+ return;
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ tdls_ctx = adapter->sessionCtx.station.pHddTdlsCtx;
+
+ qdf_spin_lock(&hdd_ctx->tdls_ct_spinlock);
+ valid_mac_entries = tdls_ctx->valid_mac_entries;
+
+ for (mac_cnt = 0; mac_cnt < valid_mac_entries; mac_cnt++) {
+ if (memcmp(tdls_ctx->ct_peer_mac_table[mac_cnt].mac_address.bytes,
+ mac_addr, QDF_MAC_ADDR_SIZE) == 0) {
+ tdls_ctx->ct_peer_mac_table[mac_cnt].rx_packet_cnt++;
+ goto rx_cnt_return;
+ }
+ }
+
+ /* If we have more than 8 peers within 30 mins. we will
+ * stop tracking till the old entries are removed
+ */
+ if (mac_cnt < TDLS_CT_MAC_MAX_TABLE_SIZE) {
+ memcpy(tdls_ctx->ct_peer_mac_table[mac_cnt].mac_address.bytes,
+ mac_addr, QDF_MAC_ADDR_SIZE);
+ tdls_ctx->valid_mac_entries = mac_cnt+1;
+ tdls_ctx->ct_peer_mac_table[mac_cnt].rx_packet_cnt = 1;
+ }
+
+rx_cnt_return:
+ qdf_spin_unlock(&hdd_ctx->tdls_ct_spinlock);
+ return;
+}
+
+/**
+ * wlan_hdd_tdls_update_tx_pkt_cnt() - update tx packet
+ * @adapter: pointer to hdd adapter
+ * @skb: pointer to sk_buff
+ *
+ * Increase the tx packet count, if the sender is not bssid and the packet is
+ * not broadcast and muticast packet
+ *
+ * This sampling information will be used in TDLS connection tracker
+ *
+ * This function expected to be called in an atomic context so blocking APIs
+ * not allowed
+ *
+ * Return: None
+ */
+void wlan_hdd_tdls_update_tx_pkt_cnt(hdd_adapter_t *adapter,
+ struct sk_buff *skb)
+{
+ hdd_context_t *hdd_ctx;
+ hdd_station_ctx_t *hdd_sta_ctx;
+ tdlsCtx_t *tdls_ctx;
+ uint8_t mac_cnt;
+ uint8_t valid_mac_entries;
+ struct qdf_mac_addr *mac_addr;
+
+ mac_addr = (struct qdf_mac_addr *)skb->data;
+ if (qdf_is_macaddr_group(mac_addr))
+ return;
+
+ hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (memcmp(hdd_sta_ctx->conn_info.bssId.bytes, mac_addr,
+ QDF_MAC_ADDR_SIZE) == 0)
+ return;
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ tdls_ctx = adapter->sessionCtx.station.pHddTdlsCtx;
+
+ qdf_spin_lock(&hdd_ctx->tdls_ct_spinlock);
+ valid_mac_entries = tdls_ctx->valid_mac_entries;
+
+ for (mac_cnt = 0; mac_cnt < valid_mac_entries; mac_cnt++) {
+ if (memcmp(tdls_ctx->ct_peer_mac_table[mac_cnt].mac_address.bytes,
+ mac_addr, QDF_MAC_ADDR_SIZE) == 0) {
+ tdls_ctx->ct_peer_mac_table[mac_cnt].tx_packet_cnt++;
+ goto tx_cnt_return;
+ }
+ }
+
+ /* If we have more than 8 peers within 30 mins. we will
+ * stop tracking till the old entries are removed
+ */
+ if (mac_cnt < TDLS_CT_MAC_MAX_TABLE_SIZE) {
+ memcpy(tdls_ctx->ct_peer_mac_table[mac_cnt].mac_address.bytes,
+ mac_addr, QDF_MAC_ADDR_SIZE);
+ tdls_ctx->ct_peer_mac_table[mac_cnt].tx_packet_cnt = 1;
+ tdls_ctx->valid_mac_entries++;
+ }
+
+tx_cnt_return:
+ qdf_spin_unlock(&hdd_ctx->tdls_ct_spinlock);
+ return;
+}
+
+/**
+ * wlan_hdd_tdls_implicit_send_discovery_request() - send discovery request
+ * @hdd_tdls_ctx: tdls context
+ *
+ * Return: None
+ */
+static
+void wlan_hdd_tdls_implicit_send_discovery_request(tdlsCtx_t *hdd_tdls_ctx)
+{
+ hdd_context_t *hdd_ctx;
+ hddTdlsPeer_t *curr_peer, *temp_peer;
+
+ ENTER();
+ if (NULL == hdd_tdls_ctx) {
+ hdd_info("hdd_tdls_ctx is NULL");
+ return;
+ }
+
+ hdd_ctx = WLAN_HDD_GET_CTX(hdd_tdls_ctx->pAdapter);
+
+ if (0 != (wlan_hdd_validate_context(hdd_ctx)))
+ return;
+
+ curr_peer = hdd_tdls_ctx->curr_candidate;
+ if (NULL == curr_peer) {
+ hdd_err("curr_peer is NULL");
+ return;
+ }
+
+ /* This function is called in mutex_lock */
+ temp_peer = wlan_hdd_tdls_is_progress(hdd_ctx, NULL, 0, false);
+ if (NULL != temp_peer) {
+ hdd_info(MAC_ADDRESS_STR " ongoing. pre_setup ignored",
+ MAC_ADDR_ARRAY(temp_peer->peerMac));
+ goto done;
+ }
+
+ if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support)
+ wlan_hdd_tdls_set_peer_link_status(curr_peer,
+ eTDLS_LINK_DISCOVERING,
+ eTDLS_LINK_SUCCESS,
+ false);
+
+ hdd_info("Implicit TDLS, Send Discovery request event");
+ cfg80211_tdls_oper_request(hdd_tdls_ctx->pAdapter->dev,
+ curr_peer->peerMac,
+ NL80211_TDLS_DISCOVERY_REQ,
+ false,
+ GFP_KERNEL);
+ hdd_tdls_ctx->discovery_sent_cnt++;
+
+ wlan_hdd_tdls_timer_restart(hdd_tdls_ctx->pAdapter,
+ &hdd_tdls_ctx->peerDiscoveryTimeoutTimer,
+ hdd_tdls_ctx->threshold_config.tx_period_t -
+ TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
+
+ hdd_info("discovery count %u timeout %u msec",
+ hdd_tdls_ctx->discovery_sent_cnt,
+ hdd_tdls_ctx->threshold_config.tx_period_t -
+ TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE);
+done:
+ hdd_tdls_ctx->curr_candidate = NULL;
+ hdd_tdls_ctx->magic = 0;
+ EXIT();
+ return;
+}
+
+/**
+ * wlan_hdd_get_conn_info() - get the tdls connection information.
+ * @hdd_ctx: hdd context
+ * @hdd_ctx: sta id
+ *
+ * Function to check tdls sta index
+ *
+ * Return: None
+ */
+static tdlsConnInfo_t *wlan_hdd_get_conn_info(hdd_context_t *hdd_ctx,
+ uint8_t idx)
+{
+ uint8_t sta_idx;
+
+ /* check if there is available index for this new TDLS STA */
+ for (sta_idx = 0; sta_idx < HDD_MAX_NUM_TDLS_STA; sta_idx++) {
+ if (idx == hdd_ctx->tdlsConnInfo[sta_idx].staId) {
+ hdd_info("tdls peer with staIdx %u exists", idx);
+ return &hdd_ctx->tdlsConnInfo[sta_idx];
+ }
+ }
+ hdd_err("tdls peer with staIdx %u not exists", idx);
+ return NULL;
+}
+
+/**
+ * wlan_hdd_tdls_idle_handler() - Check tdls idle traffic
+ * @user_data: data from tdls idle timer
+ *
+ * Function to check the tdls idle traffic and make a decision about
+ * tdls teardown
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_idle_handler(void *user_data)
+{
+ tdlsConnInfo_t *tdls_info = (tdlsConnInfo_t *) user_data;
+ hddTdlsPeer_t *curr_peer;
+ tdlsCtx_t *hdd_tdls_ctx;
+ hdd_context_t *hdd_ctx;
+ v_CONTEXT_t cds_context;
+ hdd_adapter_t *adapter;
+
+ if (!tdls_info->staId) {
+ hdd_err("peer (staidx %u) doesn't exists", tdls_info->staId);
+ return;
+ }
+
+ cds_context = cds_get_global_context();
+ if (NULL == cds_context) {
+ hdd_err("cds_context points to NULL");
+ return;
+ }
+
+ hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+ if (0 != (wlan_hdd_validate_context(hdd_ctx)))
+ return;
+
+ adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx,
+ tdls_info->sessionId);
+
+ if (!adapter) {
+ hdd_err("adapter is NULL");
+ return;
+ }
+
+ curr_peer = wlan_hdd_tdls_find_peer(adapter,
+ (u8 *) &tdls_info->peerMac.bytes[0], true);
+
+ if (NULL == curr_peer) {
+ hdd_err("Invalid tdls idle timer expired");
+ goto error_idle_return;
+ }
+
+ hdd_tdls_ctx = curr_peer->pHddTdlsCtx;
+ if (NULL == hdd_tdls_ctx) {
+ hdd_err("Invalid hdd_tdls_ctx context");
+ goto error_idle_return;
+ }
+
+ hdd_info(MAC_ADDRESS_STR " tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d",
+ MAC_ADDR_ARRAY(curr_peer->peerMac),
+ curr_peer->tx_pkt,
+ curr_peer->rx_pkt,
+ curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n);
+
+ /* Check tx/rx statistics on this tdls link for recent activities and
+ * then decide whether to tear down the link or keep it.
+ */
+ if ((curr_peer->tx_pkt >=
+ curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n) ||
+ (curr_peer->rx_pkt >=
+ curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n)) {
+ /* this tdls link got back to normal, so keep it */
+ hdd_info("tdls link to " MAC_ADDRESS_STR
+ " back to normal, will stay",
+ MAC_ADDR_ARRAY(curr_peer->peerMac));
+ } else {
+ /* this tdls link needs to get torn down */
+ hdd_info("trigger tdls link to "MAC_ADDRESS_STR
+ " down", MAC_ADDR_ARRAY(curr_peer->peerMac));
+ wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter,
+ curr_peer,
+ eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+ }
+error_idle_return:
+ return;
+}
+
+/**
+ * tdls_ct_process_idle_and_discovery() - process the traffic data
+ * @curr_peer: tdls peer needs to be examined
+ * @hdd_ctx: hdd context
+ * @hdd_tdls_ctx: tdls context
+ *
+ * Function to check the peer traffic data in idle link and tdls
+ * discovering link
+ *
+ * Return: None
+ */
+static void tdls_ct_process_idle_and_discovery(hddTdlsPeer_t *curr_peer,
+ tdlsCtx_t *hdd_tdls_ctx)
+{
+ uint16_t valid_peers;
+
+ valid_peers = wlan_hdd_tdls_connected_peers(hdd_tdls_ctx->pAdapter);
+
+ if ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
+ hdd_tdls_ctx->threshold_config.tx_packet_n) {
+ if (HDD_MAX_NUM_TDLS_STA > valid_peers) {
+ hdd_info("Tput trigger TDLS pre-setup");
+ hdd_tdls_ctx->curr_candidate = curr_peer;
+ wlan_hdd_tdls_implicit_send_discovery_request(
+ hdd_tdls_ctx);
+ } else {
+ hdd_info("Maximum peers connected already! %d",
+ valid_peers);
+ }
+ }
+}
+
+
+/**
+ * tdls_ct_process_connected_link() - process the traffic
+ * @curr_peer: tdls peer needs to be examined
+ * @hdd_ctx: hdd context
+ * @hdd_tdls_ctx: tdls context
+ *
+ * Function to check the peer traffic data in active STA
+ * session
+ *
+ * Return: None
+ */
+static void tdls_ct_process_connected_link(hddTdlsPeer_t *curr_peer,
+ hdd_context_t *hdd_ctx,
+ tdlsCtx_t *hdd_tdls_ctx)
+{
+ if ((int32_t)curr_peer->rssi <
+ (int32_t)hdd_tdls_ctx->threshold_config.rssi_teardown_threshold) {
+ hdd_warn("Tear down - low RSSI: " MAC_ADDRESS_STR "!",
+ MAC_ADDR_ARRAY(curr_peer->peerMac));
+ /* unlock the mutex here, it may used in caller function */
+ mutex_unlock(&hdd_ctx->tdls_lock);
+ wlan_hdd_tdls_indicate_teardown(hdd_tdls_ctx->pAdapter,
+ curr_peer,
+ eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+ mutex_lock(&hdd_ctx->tdls_lock);
+ return;
+ }
+
+ /* Only teardown based on non zero idle packet threshold, to address
+ * a use case where this threshold does not get consider for TEAR DOWN
+ */
+ if ((0 != hdd_tdls_ctx->threshold_config.idle_packet_n) &&
+ ((curr_peer->tx_pkt <
+ hdd_tdls_ctx->threshold_config.idle_packet_n) &&
+ (curr_peer->rx_pkt <
+ hdd_tdls_ctx->threshold_config.idle_packet_n))) {
+ if (!curr_peer->is_peer_idle_timer_initialised) {
+ uint8_t staId = (uint8_t)curr_peer->staId;
+ tdlsConnInfo_t *tdls_info;
+ tdls_info = wlan_hdd_get_conn_info(hdd_ctx, staId);
+ qdf_mc_timer_init(&curr_peer->peer_idle_timer,
+ QDF_TIMER_TYPE_SW,
+ wlan_hdd_tdls_idle_handler,
+ tdls_info);
+ curr_peer->is_peer_idle_timer_initialised = true;
+ }
+ if (QDF_TIMER_STATE_RUNNING !=
+ curr_peer->peer_idle_timer.state) {
+ hdd_warn("Tx/Rx Idle timer start: " MAC_ADDRESS_STR "!",
+ MAC_ADDR_ARRAY(curr_peer->peerMac));
+ wlan_hdd_tdls_timer_restart(hdd_tdls_ctx->pAdapter,
+ &curr_peer->peer_idle_timer,
+ hdd_tdls_ctx->threshold_config.idle_timeout_t);
+ }
+ } else if (QDF_TIMER_STATE_RUNNING ==
+ curr_peer->peer_idle_timer.state) {
+ hdd_warn("Tx/Rx Idle timer stop: " MAC_ADDRESS_STR "!",
+ MAC_ADDR_ARRAY(curr_peer->peerMac));
+ qdf_mc_timer_stop(&curr_peer->peer_idle_timer);
+ }
+}
+
+/**
+ * wlan_hdd_tdls_ct_process_cap_supported() - process TDLS supported peer.
+ * @curr_peer: tdls peer needs to be examined
+ * @hdd_ctx: hdd context
+ * @hdd_tdls_ctx: tdls context
+ *
+ * Function to check the peer traffic data for tdls supported peer
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_ct_process_cap_supported(hddTdlsPeer_t *curr_peer,
+ hdd_context_t *hdd_ctx,
+ tdlsCtx_t *hdd_tdls_ctx)
+{
+ hdd_info("tx %d, rx %d (thr.pkt %d/idle %d), rssi %d (thr.trig %d/tear %d)",
+ curr_peer->tx_pkt, curr_peer->rx_pkt,
+ hdd_tdls_ctx->threshold_config.tx_packet_n,
+ hdd_tdls_ctx->threshold_config.idle_packet_n,
+ curr_peer->rssi,
+ hdd_tdls_ctx->threshold_config.rssi_trigger_threshold,
+ hdd_tdls_ctx->threshold_config.rssi_teardown_threshold);
+
+ switch (curr_peer->link_status) {
+ case eTDLS_LINK_IDLE:
+ case eTDLS_LINK_DISCOVERING:
+ if (hdd_ctx->config->fTDLSExternalControl &&
+ (!curr_peer->isForcedPeer))
+ break;
+ tdls_ct_process_idle_and_discovery(curr_peer, hdd_tdls_ctx);
+ break;
+ case eTDLS_LINK_CONNECTED:
+ tdls_ct_process_connected_link(curr_peer, hdd_ctx,
+ hdd_tdls_ctx);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * wlan_hdd_tdls_ct_process_cap_unknown() - process unknown peer
+ * @curr_peer: tdls peer needs to be examined
+ * @hdd_ctx: hdd context
+ * @hdd_tdls_ctx: tdls context
+ *
+ * Function check the peer traffic data , when tdls capability is unknown
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_ct_process_cap_unknown(hddTdlsPeer_t *curr_peer,
+ hdd_context_t *hdd_ctx,
+ tdlsCtx_t *hdd_tdls_ctx)
+{
+ if (hdd_ctx->config->fTDLSExternalControl &&
+ (!curr_peer->isForcedPeer)) {
+ return;
+ }
+
+ hdd_info("threshold_config.tx_packet_n = %d curr_peer->tx_pkt = %d curr_peer->rx_pkt = %d ",
+ hdd_tdls_ctx->threshold_config.tx_packet_n, curr_peer->tx_pkt,
+ curr_peer->rx_pkt);
+
+ if (!TDLS_IS_CONNECTED(curr_peer) &&
+ ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
+ hdd_tdls_ctx->threshold_config.tx_packet_n)) {
+ /* Ignore discovery attempt if External Control is enabled, that
+ * is, peer is forced. In that case, continue discovery attempt
+ * regardless attempt count
+ */
+ hdd_info("TDLS UNKNOWN pre discover ");
+ if (curr_peer->isForcedPeer || curr_peer->discovery_attempt++ <
+ hdd_tdls_ctx->threshold_config.discovery_tries_n) {
+ hdd_info("TDLS UNKNOWN discover ");
+ hdd_tdls_ctx->curr_candidate = curr_peer;
+ wlan_hdd_tdls_implicit_send_discovery_request(hdd_tdls_ctx);
+ } else {
+ curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
+ wlan_hdd_tdls_set_peer_link_status(
+ curr_peer,
+ eTDLS_LINK_IDLE,
+ eTDLS_LINK_NOT_SUPPORTED,
+ false);
+ }
+ }
+}
+
+
+/**
+ * wlan_hdd_tdls_ct_process_peers() - process the peer
+ * @curr_peer: tdls peer needs to be examined
+ * @hdd_ctx: hdd context
+ * @hdd_tdls_ctx: tdls context
+ *
+ * This function check the peer capability and process the metadata from
+ * the peer
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_ct_process_peers(hddTdlsPeer_t *curr_peer,
+ hdd_context_t *hdd_ctx,
+ tdlsCtx_t *hdd_tdls_ctx)
+{
+ hdd_info(MAC_ADDRESS_STR " link_status %d tdls_support %d",
+ MAC_ADDR_ARRAY(curr_peer->peerMac),
+ curr_peer->link_status, curr_peer->tdls_support);
+
+ switch (curr_peer->tdls_support) {
+ case eTDLS_CAP_SUPPORTED:
+ wlan_hdd_tdls_ct_process_cap_supported(curr_peer, hdd_ctx,
+ hdd_tdls_ctx);
+ break;
+
+ case eTDLS_CAP_UNKNOWN:
+ wlan_hdd_tdls_ct_process_cap_unknown(curr_peer, hdd_ctx,
+ hdd_tdls_ctx);
+ break;
+ default:
+ break;
+ }
+
+}
+
+/**
+ * wlan_hdd_tdls_ct_handler() - TDLS connection tracker handler
+ * @user_data: user data from timer
+ *
+ * tdls connection tracker timer starts, when the STA connected to AP
+ * and it's scan the traffic between two STA peers and make TDLS
+ * connection and teardown, based on the traffic threshold
+ *
+ * Return: None
+ */
+static void wlan_hdd_tdls_ct_handler(void *user_data)
+{
+ int i;
+ hdd_adapter_t *adapter;
+ struct list_head *head;
+ struct list_head *pos;
+ hddTdlsPeer_t *curr_peer;
+ tdlsCtx_t *hdd_tdls_ctx;
+ hdd_context_t *hdd_ctx;
+
+ adapter = (hdd_adapter_t *)user_data;
+
+ if (NULL == adapter) {
+ hdd_err("Invalid adapter context");
+ return;
+ }
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+ if (0 != (wlan_hdd_validate_context(hdd_ctx)))
+ return;
+
+ hdd_tdls_ctx = adapter->sessionCtx.station.pHddTdlsCtx;
+
+ if (NULL == hdd_tdls_ctx) {
+ hdd_err("Invalid hdd_tdls_ctx context");
+ return;
+ }
+
+ /* If any concurrency is detected */
+ if (!hdd_ctx->enable_tdls_connection_tracker)
+ goto restart_return;
+
+ mutex_lock(&hdd_ctx->tdls_lock);
+
+ /* Update tx rx traffic sample in tdls data structures */
+ wlan_hdd_tdls_ct_sampling_tx_rx(adapter, hdd_ctx,
+ hdd_tdls_ctx);
+
+ for (i = 0; i < TDLS_PEER_LIST_SIZE; i++) {
+ head = &hdd_tdls_ctx->peer_list[i];
+ list_for_each(pos, head) {
+ curr_peer = list_entry(pos, hddTdlsPeer_t, node);
+ wlan_hdd_tdls_ct_process_peers(curr_peer, hdd_ctx,
+ hdd_tdls_ctx);
+ curr_peer->tx_pkt = 0;
+ curr_peer->rx_pkt = 0;
+ }
+ }
+
+ mutex_unlock(&hdd_ctx->tdls_lock);
+
+restart_return:
+ wlan_hdd_tdls_timer_restart(hdd_tdls_ctx->pAdapter,
+ &hdd_tdls_ctx->peer_update_timer,
+ hdd_tdls_ctx->threshold_config.tx_period_t);
+}
+
+/**
* hdd_set_tdls_scan_type - set scan during active tdls session
* @hdd_ctx: ptr to hdd context.
* @val: scan type value: 0 or 1.
diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c
index 10897f1d4160..d8649a29b630 100644
--- a/core/hdd/src/wlan_hdd_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_tx_rx.c
@@ -315,6 +315,10 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
bool granted;
uint8_t STAId = WLAN_MAX_STA_COUNT;
hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+#ifdef QCA_PKT_PROTO_TRACE
+ uint8_t proto_type = 0;
+#endif /* QCA_PKT_PROTO_TRACE */
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
#ifdef QCA_WIFI_FTM
if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
@@ -466,7 +470,25 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->queue_mapping = hdd_linux_up_to_ac_map[up];
}
+#ifdef QCA_PKT_PROTO_TRACE
+ if ((hdd_ctx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_EAPOL) ||
+ (hdd_ctx->config->gEnableDebugLog & CDS_PKT_TRAC_TYPE_DHCP)) {
+ proto_type = cds_pkt_get_proto_type(skb,
+ hdd_ctx->config->gEnableDebugLog,
+ 0);
+ if (CDS_PKT_TRAC_TYPE_EAPOL & proto_type) {
+ cds_pkt_trace_buf_update("ST:T:EPL");
+ } else if (CDS_PKT_TRAC_TYPE_DHCP & proto_type) {
+ cds_pkt_trace_buf_update("ST:T:DHC");
+ }
+ }
+#endif /* QCA_PKT_PROTO_TRACE */
+
pAdapter->stats.tx_bytes += skb->len;
+
+ if (hdd_ctx->enable_tdls_connection_tracker)
+ wlan_hdd_tdls_update_tx_pkt_cnt(pAdapter, skb);
+
++pAdapter->stats.tx_packets;
/* Zero out skb's context buffer for the driver to use */
@@ -805,6 +827,9 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
qdf_nbuf_data_addr(rxBuf),
sizeof(qdf_nbuf_data(rxBuf)), QDF_RX));
+ if (pHddCtx->enable_tdls_connection_tracker)
+ wlan_hdd_tdls_update_rx_pkt_cnt(pAdapter, skb);
+
skb->dev = pAdapter->dev;
skb->protocol = eth_type_trans(skb, skb->dev);
++pAdapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index];
@@ -966,12 +991,25 @@ static void wlan_hdd_update_unpause_time(hdd_adapter_t *adapter)
*
* Return: none
*/
-static void wlan_hdd_update_pause_time(hdd_adapter_t *adapter)
+static void wlan_hdd_update_pause_time(hdd_adapter_t *adapter,
+ uint32_t temp_map)
{
qdf_time_t curr_time = qdf_system_ticks();
+ uint8_t i;
+ qdf_time_t pause_time;
- adapter->total_pause_time += curr_time - adapter->last_time;
+ pause_time = curr_time - adapter->last_time;
+ adapter->total_pause_time += pause_time;
adapter->last_time = curr_time;
+
+ for (i = 0; i < WLAN_REASON_TYPE_MAX; i++) {
+ if (temp_map & (1 << i)) {
+ adapter->queue_oper_stats[i].total_pause_time +=
+ pause_time;
+ break;
+ }
+ }
+
}
/**
@@ -989,6 +1027,7 @@ static void wlan_hdd_update_pause_time(hdd_adapter_t *adapter)
void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
enum netif_action_type action, enum netif_reason_type reason)
{
+ uint32_t temp_map;
if ((!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) ||
(!adapter->dev)) {
@@ -1019,20 +1058,22 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
case WLAN_START_ALL_NETIF_QUEUE:
spin_lock_bh(&adapter->pause_map_lock);
+ temp_map = adapter->pause_map;
adapter->pause_map &= ~(1 << reason);
if (!adapter->pause_map) {
netif_tx_start_all_queues(adapter->dev);
- wlan_hdd_update_pause_time(adapter);
+ wlan_hdd_update_pause_time(adapter, temp_map);
}
spin_unlock_bh(&adapter->pause_map_lock);
break;
case WLAN_WAKE_ALL_NETIF_QUEUE:
spin_lock_bh(&adapter->pause_map_lock);
+ temp_map = adapter->pause_map;
adapter->pause_map &= ~(1 << reason);
if (!adapter->pause_map) {
netif_tx_wake_all_queues(adapter->dev);
- wlan_hdd_update_pause_time(adapter);
+ wlan_hdd_update_pause_time(adapter, temp_map);
}
spin_unlock_bh(&adapter->pause_map_lock);
break;
@@ -1052,10 +1093,11 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter,
case WLAN_START_ALL_NETIF_QUEUE_N_CARRIER:
spin_lock_bh(&adapter->pause_map_lock);
netif_carrier_on(adapter->dev);
+ temp_map = adapter->pause_map;
adapter->pause_map &= ~(1 << reason);
if (!adapter->pause_map) {
netif_tx_start_all_queues(adapter->dev);
- wlan_hdd_update_pause_time(adapter);
+ wlan_hdd_update_pause_time(adapter, temp_map);
}
spin_unlock_bh(&adapter->pause_map_lock);
break;
diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c
index 1024e51715e3..04c90f0bdf7a 100644
--- a/core/hdd/src/wlan_hdd_wext.c
+++ b/core/hdd/src/wlan_hdd_wext.c
@@ -9835,6 +9835,8 @@ static int __iw_set_two_ints_getnone(struct net_device *dev,
qdf_dp_trace_dump_all(value[2]);
else if (value[1] == ENABLE_DP_TRACE_LIVE_MODE)
qdf_dp_trace_enable_live_mode();
+ else if (value[1] == CLEAR_DP_TRACE_BUFFER)
+ qdf_dp_trace_clear_buffer();
break;
case WE_SET_MON_MODE_CHAN:
ret = wlan_hdd_set_mon_chan(pAdapter, value[1], value[2]);
diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h
index 1e70972a16d1..ec52065e6b7d 100644
--- a/core/mac/inc/ani_global.h
+++ b/core/mac/inc/ani_global.h
@@ -113,6 +113,27 @@ typedef struct sAniSirGlobal *tpAniSirGlobal;
/* Minimum size of vendor IE = 3 bytes of oui_data + 1 byte of data */
#define IE_VENDOR_OUI_SIZE (4)
+/*
+ * NSS cfg bit definition.
+ * STA BIT[0:1]
+ * SAP BIT[2:3]
+ * P2P_GO BIT[4:5]
+ * P2P_CLIENT BIT[6:7]
+ * IBSS BIT[8:9]
+ * TDLS BIT[10:11]
+ * P2P_DEVICE BIT[12:13]
+ * OCB BIT[14:15]
+ */
+
+#define CFG_STA_NSS(_x) ((((_x) >> 0) & 0x3) ? (((_x) >> 0) & 0x3) : 1)
+#define CFG_SAP_NSS(_x) ((((_x) >> 2) & 0x3) ? (((_x) >> 2) & 0x3) : 1)
+#define CFG_P2P_GO_NSS(_x) ((((_x) >> 4) & 0x3) ? (((_x) >> 4) & 0x3) : 1)
+#define CFG_P2P_CLI_NSS(_x) ((((_x) >> 6) & 0x3) ? (((_x) >> 6) & 0x3) : 1)
+#define CFG_IBSS_NSS(_x) ((((_x) >> 8) & 0x3) ? (((_x) >> 8) & 0x3) : 1)
+#define CFG_TDLS_NSS(_x) ((((_x) >> 10) & 0x3) ? (((_x) >> 10) & 0x3) : 1)
+#define CFG_P2P_DEV_NSS(_x) ((((_x) >> 12) & 0x3) ? (((_x) >> 12) & 0x3) : 1)
+#define CFG_OCB_NSS(_x) ((((_x) >> 14) & 0x3) ? (((_x) >> 14) & 0x3) : 1)
+
/**
* enum log_event_type - Type of event initiating bug report
* @WLAN_LOG_TYPE_NON_FATAL: Non fatal event
@@ -966,6 +987,29 @@ enum auth_tx_ack_status {
LIM_AUTH_ACK_RCD_SUCCESS,
LIM_AUTH_ACK_RCD_FAILURE,
};
+/**
+ * struct vdev_type_nss - vdev type nss structure
+ * @sta: STA Nss value.
+ * @sap: SAP Nss value.
+ * @p2p_go: P2P GO Nss value.
+ * @p2p_cli: P2P CLI Nss value.
+ * @p2p_dev: P2P device Nss value.
+ * @ibss: IBSS Nss value.
+ * @tdls: TDLS Nss value.
+ * @ocb: OCB Nss value.
+ *
+ * Holds the Nss values of different vdev types.
+ */
+struct vdev_type_nss {
+ uint8_t sta;
+ uint8_t sap;
+ uint8_t p2p_go;
+ uint8_t p2p_cli;
+ uint8_t p2p_dev;
+ uint8_t ibss;
+ uint8_t tdls;
+ uint8_t ocb;
+};
/* ------------------------------------------------------------------- */
/* / MAC Sirius parameter structure */
@@ -1027,6 +1071,10 @@ typedef struct sAniSirGlobal {
hdd_ftm_msg_processor ftm_msg_processor_callback;
bool policy_manager_enabled;
uint32_t fine_time_meas_cap;
+ /* per band chain mask support */
+ bool per_band_chainmask_supp;
+ struct vdev_type_nss vdev_type_nss_2g;
+ struct vdev_type_nss vdev_type_nss_5g;
/* 802.11p enable */
bool enable_dot11p;
diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h
index b99b359f6dc0..4e07bf4e37cb 100644
--- a/core/mac/inc/qwlan_version.h
+++ b/core/mac/inc/qwlan_version.h
@@ -42,8 +42,8 @@
#define QWLAN_VERSION_MINOR 1
#define QWLAN_VERSION_PATCH 0
#define QWLAN_VERSION_EXTRA ""
-#define QWLAN_VERSION_BUILD 12
+#define QWLAN_VERSION_BUILD 13
-#define QWLAN_VERSIONSTR "5.1.0.12"
+#define QWLAN_VERSIONSTR "5.1.0.13"
#endif /* QWLAN_VERSION_H */
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index c0b33c94f2a1..c24ec17fcb3f 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -3657,6 +3657,9 @@ typedef struct sSirUpdateChanParam {
typedef struct sSirUpdateChan {
uint8_t numChan;
+ uint8_t ht_en;
+ uint8_t vht_en;
+ uint8_t vht_24_en;
tSirUpdateChanParam chanParam[1];
} tSirUpdateChanList, *tpSirUpdateChanList;
@@ -4712,6 +4715,24 @@ struct sir_ipa_offload_enable_disable {
uint32_t enable;
};
+/**
+ * struct sir_set_ht_vht_cfg - ht, vht IE config
+ * @msg_type: message type
+ * @len: message length
+ * @pdev_id: pdev id
+ * @nss: Nss value
+ * @dot11mode: Dot11 mode.
+ *
+ * Message wrapper structure for set HT/VHT IE req.
+ */
+struct sir_set_ht_vht_cfg {
+ uint16_t msg_type;
+ uint16_t len;
+ uint32_t pdev_id;
+ uint32_t nss;
+ uint32_t dot11mode;
+};
+
/*---------------------------------------------------------------------------
WLAN_HAL_LL_NOTIFY_STATS
---------------------------------------------------------------------------*/
diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h
index 596f55889671..4aaac567966b 100644
--- a/core/mac/inc/sir_mac_prot_def.h
+++ b/core/mac/inc/sir_mac_prot_def.h
@@ -390,7 +390,13 @@
#define SIR_MAC_VHT_OPMODE_EID 199
#define SIR_MAC_MAX_SUPPORTED_MCS_SET 16
+#define VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390
+#define VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1 390
+#define VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780
+#define VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_2_2 780
+
#define VHT_MCS_1x1 0xFFFC
+#define VHT_MCS_2x2 0xFFF3
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
#define SIR_MAC_QCOM_VENDOR_EID 200
diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h
index e6dfb2dda66a..160ada158e40 100644
--- a/core/mac/inc/wni_api.h
+++ b/core/mac/inc/wni_api.h
@@ -250,6 +250,7 @@ enum eWniMsgTypes {
eWNI_SME_SET_ANTENNA_MODE_RESP,
eWNI_SME_TSF_EVENT,
eWNI_SME_MON_INIT_SESSION,
+ eWNI_SME_PDEV_SET_HT_VHT_IE,
eWNI_SME_MSG_TYPES_END
};
diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h
index 215667673307..7019d99d319a 100644
--- a/core/mac/src/include/parser_api.h
+++ b/core/mac/src/include/parser_api.h
@@ -55,6 +55,9 @@
#define IS_2X2_CHAIN(__chain) ((__chain & 0x3) == 0x3)
#define DISABLE_NSS2_MCS 0xC
+#define NSS_1x1_MODE 1
+#define NSS_2x2_MODE 2
+
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
#define QCOM_VENDOR_IE_MCC_AVOID_CH 0x01
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 476e4a68b752..26910c801fb4 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -611,6 +611,7 @@ typedef struct sSirMbMsgP2p {
#define SIR_HAL_SET_WISA_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 343)
#define SIR_HAL_SET_ADAPT_DWELLTIME_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 344)
+#define SIR_HAL_SET_PDEV_IE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 345)
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
/* CFG message types */
diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h
index a5bf8f77f0b3..8f3f118cd429 100644
--- a/core/mac/src/pe/include/lim_session.h
+++ b/core/mac/src/pe/include/lim_session.h
@@ -475,6 +475,7 @@ typedef struct sPESession /* Added to Support BT-AMP */
bool add_bss_failed;
/* To hold OBSS Scan IE Parameters */
struct obss_scanparam obss_ht40_scanparam;
+ uint8_t vdev_nss;
/* Supported NSS is intersection of self and peer NSS */
bool supported_nss_1x1;
bool is_ext_caps_present;
diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c
index 7144f945af41..2a1dfec655e9 100644
--- a/core/mac/src/pe/lim/lim_assoc_utils.c
+++ b/core/mac/src/pe/lim/lim_assoc_utils.c
@@ -1409,8 +1409,8 @@ tSirRetStatus lim_populate_vht_mcs_set(tpAniSirGlobal mac_ctx,
QDF_MIN(rates->vhtRxHighestDataRate,
peer_vht_caps->rxHighSupDataRate);
- if (mac_ctx->roam.configParam.enable2x2) {
- if (session_entry && mac_ctx->lteCoexAntShare &&
+ if (session_entry && session_entry->vdev_nss == 2) {
+ if (mac_ctx->lteCoexAntShare &&
IS_24G_CH(session_entry->currentOperChannel)) {
if (IS_2X2_CHAIN(session_entry->chainMask))
mcs_map_mask2x2 = MCSMAPMASK2x2;
@@ -1627,6 +1627,8 @@ lim_populate_own_rate_set(tpAniSirGlobal mac_ctx,
return eSIR_FAILURE;
}
+ if (session_entry->vdev_nss == 1)
+ rates->supportedMCSSet[1] = 0;
/*
* if supported MCS Set of the peer is passed in,
* then do the intersection
@@ -1766,8 +1768,12 @@ lim_populate_peer_rate_set(tpAniSirGlobal pMac,
)
return eSIR_FAILURE;
}
- /* if supported MCS Set of the peer is passed in, then do the intersection */
- /* else use the MCS set from local CFG. */
+ if (psessionEntry->vdev_nss == 1)
+ pRates->supportedMCSSet[1] = 0;
+
+ /* if supported MCS Set of the peer is passed in, then do the
+ * intersection, else use the MCS set from local CFG.
+ */
if (pSupportedMCSSet != NULL) {
for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++)
pRates->supportedMCSSet[i] &=
@@ -1991,6 +1997,9 @@ tSirRetStatus lim_populate_matching_rate_set(tpAniSirGlobal mac_ctx,
return eSIR_FAILURE;
}
+ if (session_entry->vdev_nss == 1)
+ mcs_set[1] = 0;
+
for (i = 0; i < val; i++)
sta_ds->supportedRates.supportedMCSSet[i] =
mcs_set[i] & supported_mcs_set[i];
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 bebe8120dafc..d8031c2c5bfa 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -1414,6 +1414,7 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
msg->bodyptr = NULL;
}
break;
+ case eWNI_SME_PDEV_SET_HT_VHT_IE:
case eWNI_SME_SYS_READY_IND:
case eWNI_SME_JOIN_REQ:
case eWNI_SME_REASSOC_REQ:
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 e58f60020122..f2d1d99ad968 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
@@ -116,7 +116,6 @@ static void lim_process_update_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg);
extern void pe_register_wma_handle(tpAniSirGlobal pMac,
tSirSmeReadyReq *ready_req);
-
static void lim_process_ext_change_channel(tpAniSirGlobal mac_ctx,
uint32_t *msg);
@@ -224,7 +223,7 @@ static QDF_STATUS lim_process_set_dual_mac_cfg_req(tpAniSirGlobal mac,
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
- lim_log(mac, LOGE, FL("vos_mem_malloc failed"));
+ lim_log(mac, LOGE, FL("qdf_mem_malloc failed"));
/* Free the active command list
* Probably the malloc is going to fail there as well?!
*/
@@ -631,6 +630,7 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
uint8_t sme_session_id = 0;
uint16_t sme_transaction_id = 0;
uint32_t chanwidth;
+ struct vdev_type_nss *vdev_type_nss;
tSirRetStatus cfg_get_wmi_dfs_master_param = eSIR_SUCCESS;
/* FEATURE_WLAN_DIAG_SUPPORT */
@@ -779,10 +779,6 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
session->vhtCapability);
session->txLdpcIniFeatureEnabled =
sme_start_bss_req->txLdpcIniFeatureEnabled;
- if (mac_ctx->roam.configParam.enable2x2)
- session->nss = 2;
- else
- session->nss = 1;
#ifdef WLAN_FEATURE_11W
session->limRmfEnabled =
sme_start_bss_req->pmfCapable ? 1 : 0;
@@ -797,6 +793,11 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
(void *)&sme_start_bss_req->extendedRateSet,
sizeof(tSirMacRateSet));
+ if (IS_5G_CH(session->currentOperChannel))
+ vdev_type_nss = &mac_ctx->vdev_type_nss_5g;
+ else
+ vdev_type_nss = &mac_ctx->vdev_type_nss_2g;
+
switch (sme_start_bss_req->bssType) {
case eSIR_INFRA_AP_MODE:
lim_configure_ap_start_bss_session(mac_ctx, session,
@@ -806,6 +807,9 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
sme_start_bss_req->txbf_ini_enabled;
session->txbf_csn_value =
sme_start_bss_req->txbf_csn_val;
+ session->vdev_nss = vdev_type_nss->sap;
+ } else {
+ session->vdev_nss = vdev_type_nss->p2p_go;
}
break;
case eSIR_IBSS_MODE:
@@ -819,6 +823,7 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
* will be updated upon key installation
*/
session->encryptType = eSIR_ED_NONE;
+ session->vdev_nss = vdev_type_nss->ibss;
break;
@@ -834,6 +839,9 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
break;
}
+ lim_log(mac_ctx, LOG1, FL("persona - %d, nss - %d"),
+ session->pePersona, session->vdev_nss);
+ session->nss = session->vdev_nss;
/*
* Allocate memory for the array of
* parsed (Re)Assoc request structure
@@ -1202,7 +1210,8 @@ static QDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac,
uint8_t *ht_cap_ie;
tSirMsgQ msg;
uint16_t i, len;
- uint16_t ht_cap_len = 0, addn_ie_len = 0;
+ uint16_t ht_cap_len = 0;
+ uint16_t addn_ie_len = 0;
uint8_t *vht_cap_ie;
uint16_t vht_cap_len = 0;
tSirRetStatus status, rc = eSIR_SUCCESS;
@@ -1236,29 +1245,30 @@ static QDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac,
* so allocate the memory for (numChannels - 1) and uIEFieldLen
*/
len = sizeof(tSirScanOffloadReq) +
- (pScanReq->channelList.numChannels - 1) + pScanReq->uIEFieldLen;
-
- if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) {
- lim_log(pMac, LOG1,
- FL("Adding HT Caps IE since dot11mode=%d"),
- pScanReq->dot11mode);
- /* 2 bytes for EID and Length */
- ht_cap_len = 2 + sizeof(tHtCaps);
- len += ht_cap_len;
- addn_ie_len += ht_cap_len;
- }
+ (pScanReq->channelList.numChannels - 1) +
+ pScanReq->uIEFieldLen;
+ if (!pMac->per_band_chainmask_supp) {
+ if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) {
+ lim_log(pMac, LOG1, FL(
+ "Adding HT Caps IE since dot11mode=%d"),
+ pScanReq->dot11mode);
+ /* 2 bytes for EID and Length */
+ ht_cap_len = 2 + sizeof(tHtCaps);
+ len += ht_cap_len;
+ addn_ie_len += ht_cap_len;
+ }
- if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) {
- lim_log(pMac, LOG1,
- FL("Adding VHT Caps IE since dot11mode=%d"),
- pScanReq->dot11mode);
- /* 2 bytes for EID and Length */
- vht_cap_len = 2 + sizeof(tSirMacVHTCapabilityInfo) +
- sizeof(tSirVhtMcsInfo);
- len += vht_cap_len;
- addn_ie_len += vht_cap_len;
+ if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) {
+ lim_log(pMac, LOG1, FL(
+ "Adding VHT Caps IE since dot11mode=%d"),
+ pScanReq->dot11mode);
+ /* 2 bytes for EID and Length */
+ vht_cap_len = 2 + sizeof(tSirMacVHTCapabilityInfo) +
+ sizeof(tSirVhtMcsInfo);
+ len += vht_cap_len;
+ addn_ie_len += vht_cap_len;
+ }
}
-
pScanOffloadReq = qdf_mem_malloc(len);
if (NULL == pScanOffloadReq) {
lim_log(pMac, LOGE,
@@ -1331,33 +1341,33 @@ static QDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac,
pScanOffloadReq->uIEFieldOffset,
(uint8_t *) pScanReq + pScanReq->uIEFieldOffset,
pScanReq->uIEFieldLen);
+ if (!pMac->per_band_chainmask_supp) {
+ /* Copy HT Capability info if dot11mode is HT */
+ if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) {
+ /* Populate EID and Length field here */
+ ht_cap_ie = (uint8_t *) pScanOffloadReq +
+ pScanOffloadReq->uIEFieldOffset +
+ pScanOffloadReq->uIEFieldLen;
+ qdf_mem_set(ht_cap_ie, ht_cap_len, 0);
+ *ht_cap_ie = SIR_MAC_HT_CAPABILITIES_EID;
+ *(ht_cap_ie + 1) = ht_cap_len - 2;
+ lim_set_ht_caps(pMac, NULL, ht_cap_ie, ht_cap_len);
+ pScanOffloadReq->uIEFieldLen += ht_cap_len;
+ }
- /* Copy HT Capability info if dot11mode is HT */
- if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) {
- /* Populate EID and Length field here */
- ht_cap_ie = (uint8_t *) pScanOffloadReq +
- pScanOffloadReq->uIEFieldOffset +
- pScanOffloadReq->uIEFieldLen;
- qdf_mem_set(ht_cap_ie, ht_cap_len, 0);
- *ht_cap_ie = SIR_MAC_HT_CAPABILITIES_EID;
- *(ht_cap_ie + 1) = ht_cap_len - 2;
- lim_set_ht_caps(pMac, NULL, ht_cap_ie, ht_cap_len);
- pScanOffloadReq->uIEFieldLen += ht_cap_len;
- }
-
- /* Copy VHT Capability info if dot11mode is VHT Capable */
- if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) {
- /* Populate EID and Length field here */
- vht_cap_ie = (uint8_t *) pScanOffloadReq +
- pScanOffloadReq->uIEFieldOffset +
- pScanOffloadReq->uIEFieldLen;
- qdf_mem_set(vht_cap_ie, vht_cap_len, 0);
- *vht_cap_ie = SIR_MAC_VHT_CAPABILITIES_EID;
- *(vht_cap_ie + 1) = vht_cap_len - 2;
- lim_set_vht_caps(pMac, NULL, vht_cap_ie, vht_cap_len);
- pScanOffloadReq->uIEFieldLen += vht_cap_len;
+ /* Copy VHT Capability info if dot11mode is VHT Capable */
+ if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) {
+ /* Populate EID and Length field here */
+ vht_cap_ie = (uint8_t *) pScanOffloadReq +
+ pScanOffloadReq->uIEFieldOffset +
+ pScanOffloadReq->uIEFieldLen;
+ qdf_mem_set(vht_cap_ie, vht_cap_len, 0);
+ *vht_cap_ie = SIR_MAC_VHT_CAPABILITIES_EID;
+ *(vht_cap_ie + 1) = vht_cap_len - 2;
+ lim_set_vht_caps(pMac, NULL, vht_cap_ie, vht_cap_len);
+ pScanOffloadReq->uIEFieldLen += vht_cap_len;
+ }
}
-
rc = wma_post_ctrl_msg(pMac, &msg);
if (rc != eSIR_SUCCESS) {
lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() return failure"));
@@ -1570,6 +1580,7 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
uint16_t ie_len;
uint8_t *vendor_ie;
tSirBssDescription *bss_desc;
+ struct vdev_type_nss *vdev_type_nss;
/* FEATURE_WLAN_DIAG_SUPPORT */
#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
@@ -1750,10 +1761,23 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
session->supported_nss_1x1,
session->pePersona,
sme_join_req->cbMode);
- if (mac_ctx->roam.configParam.enable2x2)
- session->nss = 2;
+
+ /*Store Persona */
+ session->pePersona = sme_join_req->staPersona;
+ QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO,
+ FL("PE PERSONA=%d cbMode %u"),
+ session->pePersona, sme_join_req->cbMode);
+ /* Copy The channel Id to the session Table */
+ session->currentOperChannel = bss_desc->channelId;
+ if (IS_5G_CH(session->currentOperChannel))
+ vdev_type_nss = &mac_ctx->vdev_type_nss_5g;
else
- session->nss = 1;
+ vdev_type_nss = &mac_ctx->vdev_type_nss_2g;
+ if (session->pePersona == QDF_P2P_CLIENT_MODE)
+ session->vdev_nss = vdev_type_nss->p2p_cli;
+ else
+ session->vdev_nss = vdev_type_nss->sta;
+ session->nss = session->vdev_nss;
session->vhtCapability =
IS_DOT11_MODE_VHT(session->dot11mode);
if (session->vhtCapability) {
@@ -1801,8 +1825,6 @@ __lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
/*Phy mode */
session->gLimPhyMode = bss_desc->nwType;
handle_ht_capabilityand_ht_info(mac_ctx, session);
- /* Copy The channel Id to the session Table */
- session->currentOperChannel = bss_desc->channelId;
/* cbMode is already merged value of peer and self -
* done by csr in csr_get_cb_mode_from_ies */
session->htSupportedChannelWidthSet =
@@ -4698,6 +4720,179 @@ static void lim_register_mgmt_frame_ind_cb(tpAniSirGlobal mac_ctx,
}
/**
+ * lim_set_pdev_ht_ie() - sends the set HT IE req to FW
+ * @mac_ctx: Pointer to Global MAC structure
+ * @pdev_id: pdev id to set the IE.
+ * @nss: Nss values to prepare the HT IE.
+ *
+ * Prepares the HT IE with self capabilities for different
+ * Nss values and sends the set HT IE req to FW.
+ *
+ * Return: None
+ */
+static void lim_set_pdev_ht_ie(tpAniSirGlobal mac_ctx, uint8_t pdev_id,
+ uint8_t nss)
+{
+ struct set_ie_param *ie_params;
+ tSirMsgQ msg;
+ tSirRetStatus rc = eSIR_SUCCESS;
+ uint8_t *p_ie = NULL;
+ tHtCaps *p_ht_cap;
+ int i;
+
+ for (i = nss; i > 0; i--) {
+ ie_params = qdf_mem_malloc(sizeof(*ie_params));
+ if (NULL == ie_params) {
+ lim_log(mac_ctx, LOGE, FL("mem alloc failed"));
+ return;
+ }
+ ie_params->nss = i;
+ ie_params->pdev_id = pdev_id;
+ ie_params->ie_type = DOT11_HT_IE;
+ /* 2 for IE len and EID */
+ ie_params->ie_len = 2 + sizeof(tHtCaps);
+ ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len);
+ if (NULL == ie_params->ie_ptr) {
+ qdf_mem_free(ie_params);
+ lim_log(mac_ctx, LOGE, FL("mem alloc failed"));
+ return;
+ }
+ *ie_params->ie_ptr = SIR_MAC_HT_CAPABILITIES_EID;
+ *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2;
+ lim_set_ht_caps(mac_ctx, NULL, ie_params->ie_ptr,
+ ie_params->ie_len);
+
+ if (NSS_1x1_MODE == i) {
+ p_ie = lim_get_ie_ptr_new(mac_ctx, ie_params->ie_ptr,
+ ie_params->ie_len,
+ DOT11F_EID_HTCAPS, ONE_BYTE);
+ p_ht_cap = (tHtCaps *)&p_ie[2];
+ p_ht_cap->supportedMCSSet[1] = 0;
+ p_ht_cap->txSTBC = 0;
+ }
+
+ msg.type = WMA_SET_PDEV_IE_REQ;
+ msg.bodyptr = ie_params;
+ msg.bodyval = 0;
+
+ rc = wma_post_ctrl_msg(mac_ctx, &msg);
+ if (rc != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("wma_post_ctrl_msg() return failure"));
+ qdf_mem_free(ie_params->ie_ptr);
+ qdf_mem_free(ie_params);
+ return;
+ }
+ }
+}
+
+/**
+ * lim_set_pdev_vht_ie() - sends the set VHT IE to req FW
+ * @mac_ctx: Pointer to Global MAC structure
+ * @pdev_id: pdev id to set the IE.
+ * @nss: Nss values to prepare the VHT IE.
+ *
+ * Prepares the VHT IE with self capabilities for different
+ * Nss values and sends the set VHT IE req to FW.
+ *
+ * Return: None
+ */
+static void lim_set_pdev_vht_ie(tpAniSirGlobal mac_ctx, uint8_t pdev_id,
+ uint8_t nss)
+{
+ struct set_ie_param *ie_params;
+ tSirMsgQ msg;
+ tSirRetStatus rc = eSIR_SUCCESS;
+ uint8_t *p_ie = NULL;
+ tSirMacVHTCapabilityInfo *vht_cap;
+ int i;
+ tSirVhtMcsInfo *vht_mcs;
+
+ for (i = nss; i > 0; i--) {
+ ie_params = qdf_mem_malloc(sizeof(*ie_params));
+ if (NULL == ie_params) {
+ lim_log(mac_ctx, LOGE, FL("mem alloc failed"));
+ return;
+ }
+ ie_params->nss = i;
+ ie_params->pdev_id = pdev_id;
+ ie_params->ie_type = DOT11_VHT_IE;
+ /* 2 for IE len and EID */
+ ie_params->ie_len = 2 + sizeof(tSirMacVHTCapabilityInfo) +
+ sizeof(tSirVhtMcsInfo);
+ ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len);
+ if (NULL == ie_params->ie_ptr) {
+ qdf_mem_free(ie_params);
+ lim_log(mac_ctx, LOGE, FL("mem alloc failed"));
+ return;
+ }
+ *ie_params->ie_ptr = SIR_MAC_VHT_CAPABILITIES_EID;
+ *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2;
+ lim_set_vht_caps(mac_ctx, NULL, ie_params->ie_ptr,
+ ie_params->ie_len);
+
+ if (NSS_1x1_MODE == i) {
+ p_ie = lim_get_ie_ptr_new(mac_ctx, ie_params->ie_ptr,
+ ie_params->ie_len,
+ DOT11F_EID_VHTCAPS, ONE_BYTE);
+ vht_cap = (tSirMacVHTCapabilityInfo *)&p_ie[2];
+ vht_cap->txSTBC = 0;
+ vht_mcs =
+ (tSirVhtMcsInfo *)&p_ie[2 +
+ sizeof(tSirMacVHTCapabilityInfo)];
+ vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS;
+ vht_mcs->rxHighest =
+ VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
+ vht_mcs->txMcsMap |= DISABLE_NSS2_MCS;
+ vht_mcs->txHighest =
+ VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
+ }
+ msg.type = WMA_SET_PDEV_IE_REQ;
+ msg.bodyptr = ie_params;
+ msg.bodyval = 0;
+
+ rc = wma_post_ctrl_msg(mac_ctx, &msg);
+ if (rc != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("wma_post_ctrl_msg failure"));
+ qdf_mem_free(ie_params->ie_ptr);
+ qdf_mem_free(ie_params);
+ return;
+ }
+ }
+}
+
+/**
+ * lim_process_set_pdev_IEs() - process the set pdev IE req
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: Pointer to the SME message buffer
+ *
+ * This function is called by limProcessMessageQueue(). This
+ * function sets the PDEV IEs to the FW.
+ *
+ * Return: None
+ */
+static void lim_process_set_pdev_IEs(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ struct sir_set_ht_vht_cfg *ht_vht_cfg;
+
+ ht_vht_cfg = (struct sir_set_ht_vht_cfg *)msg_buf;
+
+ if (NULL == ht_vht_cfg) {
+ lim_log(mac_ctx, LOGE, FL("NULL ht_vht_cfg"));
+ return;
+ }
+
+ lim_log(mac_ctx, LOG1, FL("rcvd set pdev ht vht ie req with nss = %d"),
+ ht_vht_cfg->nss);
+ lim_set_pdev_ht_ie(mac_ctx, ht_vht_cfg->pdev_id, ht_vht_cfg->nss);
+
+ if (IS_DOT11_MODE_VHT(ht_vht_cfg->dot11mode))
+ lim_set_pdev_vht_ie(mac_ctx, ht_vht_cfg->pdev_id,
+ ht_vht_cfg->nss);
+}
+
+/**
* lim_process_sme_req_messages()
*
***FUNCTION:
@@ -4938,6 +5133,9 @@ bool lim_process_sme_req_messages(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
case eWNI_SME_SET_ANTENNA_MODE_REQ:
lim_process_set_antenna_mode_req(pMac, pMsgBuf);
break;
+ case eWNI_SME_PDEV_SET_HT_VHT_IE:
+ lim_process_set_pdev_IEs(pMac, pMsgBuf);
+ break;
default:
qdf_mem_free((void *)pMsg->bodyptr);
pMsg->bodyptr = NULL;
diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h
index b2ebe12ecef1..ec75fca557b2 100644
--- a/core/sap/inc/sap_api.h
+++ b/core/sap/inc/sap_api.h
@@ -804,8 +804,9 @@ QDF_STATUS wlansap_set_wps_ie(void *p_cds_gctx, tSap_WPSIE *pWPSIe);
QDF_STATUS wlansap_update_wps_ie(void *p_cds_gctx);
QDF_STATUS wlansap_stop_Wps(void *p_cds_gctx);
QDF_STATUS wlansap_get_wps_state(void *p_cds_gctx, bool *pbWPSState);
-
void *wlansap_open(void *p_cds_gctx);
+QDF_STATUS wlansap_global_init(void);
+QDF_STATUS wlansap_global_deinit(void);
QDF_STATUS wlansap_start(void *p_cds_gctx, enum tQDF_ADAPTER_MODE mode,
uint8_t *addr, uint32_t *session_id);
QDF_STATUS wlansap_stop(void *p_cds_gctx);
diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c
index a541031a9141..d0b3a00582c0 100644
--- a/core/sap/src/sap_api_link_cntl.c
+++ b/core/sap/src/sap_api_link_cntl.c
@@ -808,20 +808,24 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId,
eRoamCmdStatus roam_status, eCsrRoamResult roam_result)
{
/* sap_ctx value */
- ptSapContext sap_ctx = (ptSapContext) ctx;
+ ptSapContext sap_ctx;
/* State machine event */
tWLAN_SAPEvent sap_event;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
- tHalHandle hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx);
+ tHalHandle hal;
tpAniSirGlobal mac_ctx = NULL;
uint8_t intf;
- if (NULL == hal) {
+ if (QDF_IS_STATUS_ERROR(wlansap_context_get((ptSapContext)ctx)))
+ return QDF_STATUS_E_FAILURE;
+
+ sap_ctx = (ptSapContext) ctx;
+ hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx);
+ if (!hal) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
- FL("Invalid hal"));
- qdf_ret_status = QDF_STATUS_E_NOMEM;
- return qdf_ret_status;
+ FL("Invalid handle"));
+ return QDF_STATUS_E_NOMEM;
}
mac_ctx = PMAC_STRUCT(hal);
@@ -1214,5 +1218,6 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId,
roam_result);
break;
}
+ wlansap_context_put(sap_ctx);
return qdf_ret_status;
}
diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c
index 0db2f1e618fc..0297953b7144 100644
--- a/core/sap/src/sap_fsm.c
+++ b/core/sap/src/sap_fsm.c
@@ -2375,7 +2375,7 @@ QDF_STATUS sap_goto_channel_sel(ptSapContext sap_context,
* Return: QDF_STATUS
*/
-#define SAP_OPEN_SESSION_TIMEOUT 500
+#define SAP_OPEN_SESSION_TIMEOUT 2000
QDF_STATUS sap_open_session(tHalHandle hHal, ptSapContext sapContext,
uint32_t *session_id)
{
diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h
index 435fcb52854e..29ae041764a8 100644
--- a/core/sap/src/sap_internal.h
+++ b/core/sap/src/sap_internal.h
@@ -269,8 +269,6 @@ typedef struct sSapContext {
/*----------------------------------------------------------------------------
* External declarations for global context
* -------------------------------------------------------------------------*/
-/* The main per-Physical Link (per WLAN association) context. */
-extern ptSapContext gp_sap_ctx;
/*----------------------------------------------------------------------------
* SAP state machine event definition
@@ -290,6 +288,8 @@ typedef struct sWLAN_SAPEvent {
/*----------------------------------------------------------------------------
* Function Declarations and Documentation
* -------------------------------------------------------------------------*/
+QDF_STATUS wlansap_context_get(ptSapContext ctx);
+void wlansap_context_put(ptSapContext ctx);
QDF_STATUS
wlansap_scan_callback
diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c
index b75f71e4d269..9965c2b8ff7c 100644
--- a/core/sap/src/sap_module.c
+++ b/core/sap/src/sap_module.c
@@ -44,6 +44,7 @@
* -------------------------------------------------------------------------*/
#include "qdf_trace.h"
#include "qdf_util.h"
+#include "qdf_atomic.h"
/* Pick up the sme callback registration API */
#include "sme_api.h"
@@ -73,11 +74,13 @@
* -------------------------------------------------------------------------*/
/* No! Get this from CDS. */
/* The main per-Physical Link (per WLAN association) context. */
-ptSapContext gp_sap_ctx;
+static ptSapContext gp_sap_ctx[SAP_MAX_NUM_SESSION];
+static qdf_atomic_t sap_ctx_ref_count[SAP_MAX_NUM_SESSION];
/*----------------------------------------------------------------------------
* Static Variable Definitions
* -------------------------------------------------------------------------*/
+static qdf_mutex_t sap_context_lock;
/*----------------------------------------------------------------------------
* Static Function Declarations and Definitions
@@ -92,6 +95,159 @@ ptSapContext gp_sap_ctx;
* -------------------------------------------------------------------------*/
/**
+ * wlansap_global_init() - Initialize SAP globals
+ *
+ * Initializes the SAP global data structures
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlansap_global_init(void)
+{
+ uint32_t i;
+
+ if (QDF_IS_STATUS_ERROR(qdf_mutex_create(&sap_context_lock))) {
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ "failed to init sap_context_lock");
+ return QDF_STATUS_E_FAULT;
+ }
+
+ for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
+ gp_sap_ctx[i] = NULL;
+ qdf_atomic_init(&sap_ctx_ref_count[i]);
+ }
+
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+ "%s: sap global context initialized", __func__);
+
+ return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wlansap_global_deinit() - De-initialize SAP globals
+ *
+ * De-initializes the SAP global data structures
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlansap_global_deinit(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
+ if (gp_sap_ctx[i]) {
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ "we could be leaking context:%d", i);
+ }
+ gp_sap_ctx[i] = NULL;
+ qdf_atomic_init(&sap_ctx_ref_count[i]);
+ }
+
+ if (QDF_IS_STATUS_ERROR(qdf_mutex_destroy(&sap_context_lock))) {
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ "failed to destroy sap_context_lock");
+ return QDF_STATUS_E_FAULT;
+ }
+
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+ "%s: sap global context deinitialized", __func__);
+
+ return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wlansap_save_context() - Save the context in global SAP context
+ * @ctx: SAP context to be stored
+ *
+ * Stores the given SAP context in the global SAP context array
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS wlansap_save_context(ptSapContext ctx)
+{
+ uint32_t i;
+
+ qdf_mutex_acquire(&sap_context_lock);
+ for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
+ if (gp_sap_ctx[i] == NULL) {
+ gp_sap_ctx[i] = ctx;
+ qdf_atomic_inc(&sap_ctx_ref_count[i]);
+ qdf_mutex_release(&sap_context_lock);
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
+ "%s: sap context saved at index:%d",
+ __func__, i);
+ return QDF_STATUS_SUCCESS;
+ }
+ }
+ qdf_mutex_release(&sap_context_lock);
+
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ "%s: failed to save sap context", __func__);
+
+ return QDF_STATUS_E_FAILURE;
+}
+
+/**
+ * wlansap_context_get() - Verify SAP context and increment ref count
+ * @ctx: Context to be checked
+ *
+ * Verifies the SAP context and increments the reference count maintained for
+ * the corresponding SAP context.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlansap_context_get(ptSapContext ctx)
+{
+ uint32_t i;
+
+ qdf_mutex_acquire(&sap_context_lock);
+ for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
+ if (ctx && (gp_sap_ctx[i] == ctx)) {
+ qdf_atomic_inc(&sap_ctx_ref_count[i]);
+ qdf_mutex_release(&sap_context_lock);
+ return QDF_STATUS_SUCCESS;
+ }
+ }
+ qdf_mutex_release(&sap_context_lock);
+
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ "%s: sap session is not valid", __func__);
+ return QDF_STATUS_E_FAILURE;
+}
+
+/**
+ * wlansap_context_put() - Check the reference count and free SAP context
+ * @ctx: SAP context to be checked and freed
+ *
+ * Checks the reference count and frees the SAP context
+ *
+ * Return: None
+ */
+void wlansap_context_put(ptSapContext ctx)
+{
+ uint32_t i;
+
+ if (!ctx)
+ return;
+
+ qdf_mutex_acquire(&sap_context_lock);
+ for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
+ if (gp_sap_ctx[i] == ctx) {
+ if (qdf_atomic_dec_and_test(&sap_ctx_ref_count[i])) {
+ qdf_mem_free(ctx);
+ gp_sap_ctx[i] = NULL;
+ QDF_TRACE(QDF_MODULE_ID_SAP,
+ QDF_TRACE_LEVEL_INFO,
+ "%s: sap session freed: %d",
+ __func__, i);
+ }
+ qdf_mutex_release(&sap_context_lock);
+ return;
+ }
+ }
+ qdf_mutex_release(&sap_context_lock);
+}
+
+/**
* wlansap_open() - WLAN SAP open function call
* @p_cds_gctx: Pointer to the global cds context; a handle to SAP's
*
@@ -104,6 +260,7 @@ ptSapContext gp_sap_ctx;
void *wlansap_open(void *p_cds_gctx)
{
ptSapContext pSapCtx = NULL;
+ QDF_STATUS status;
/* dynamically allocate the sapContext */
pSapCtx = (ptSapContext) qdf_mem_malloc(sizeof(tSapContext));
@@ -122,8 +279,14 @@ void *wlansap_open(void *p_cds_gctx)
/* Setup the "link back" to the CDS context */
pSapCtx->p_cds_gctx = p_cds_gctx;
- /* Store a pointer to the SAP context provided by CDS */
- gp_sap_ctx = pSapCtx;
+ /* Save the SAP context pointer */
+ status = wlansap_save_context(pSapCtx);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+ "%s: failed to save SAP context", __func__);
+ qdf_mem_free(pSapCtx);
+ return NULL;
+ }
return pSapCtx;
} /* wlansap_open */
@@ -296,7 +459,7 @@ QDF_STATUS wlansap_close(void *pCtx)
/* empty queues/lists/pkts if any */
wlansap_clean_cb(pSapCtx, true);
- qdf_mem_free(pSapCtx);
+ wlansap_context_put(pSapCtx);
return QDF_STATUS_SUCCESS;
} /* wlansap_close */
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 6cebcff38770..11557c7b237f 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -82,6 +82,7 @@
#define SME_CONFIG_TO_ROAM_CONFIG 1
#define ROAM_CONFIG_TO_SME_CONFIG 2
+#define NUM_OF_BANDS 2
/*--------------------------------------------------------------------------
Type declarations
------------------------------------------------------------------------*/
@@ -1123,4 +1124,8 @@ uint32_t sme_get_wni_dot11_mode(tHalHandle hal);
QDF_STATUS sme_create_mon_session(tHalHandle hal_handle, uint8_t *bssid);
QDF_STATUS sme_set_adaptive_dwelltime_config(tHalHandle hal,
struct adaptive_dwelltime_params *dwelltime_params);
+void sme_set_pdev_ht_vht_ies(tHalHandle hHal, bool enable2x2);
+
+void sme_update_vdev_type_nss(tHalHandle hal, uint8_t max_supp_nss,
+ uint32_t vdev_type_nss, eCsrBand band);
#endif /* #if !defined( __SME_API_H ) */
diff --git a/core/sme/inc/sme_inside.h b/core/sme/inc/sme_inside.h
index cf5614ded55d..5a6600a7d983 100644
--- a/core/sme/inc/sme_inside.h
+++ b/core/sme/inc/sme_inside.h
@@ -230,6 +230,9 @@ QDF_STATUS oem_data_process_oem_data_req_command(tpAniSirGlobal pMac,
tSmeCmd *pCommand);
#endif
+void csr_get_vdev_type_nss(tpAniSirGlobal mac_ctx,
+ enum tQDF_ADAPTER_MODE dev_mode,
+ uint8_t *nss_2g, uint8_t *nss_5g);
QDF_STATUS csr_process_add_sta_session_command(tpAniSirGlobal pMac,
tSmeCmd *pCommand);
QDF_STATUS csr_process_add_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg);
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 011227bd8b6b..e8abaa9ed318 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -15112,6 +15112,7 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg)
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->lteCoexAntShare = cfg->lte_coex_ant_share;
+ mac_ctx->per_band_chainmask_supp = cfg->per_band_chainmask_supp;
mac_ctx->beacon_offload = cfg->beacon_offload;
mac_ctx->pmf_offload = cfg->pmf_offload;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
@@ -15576,7 +15577,6 @@ QDF_STATUS sme_create_mon_session(tHalHandle hal_handle, tSirMacAddr bss_id)
return status;
}
-
/**
* sme_set_adaptive_dwelltime_config() - Update Adaptive dwelltime configuration
* @hal: The handle returned by macOpen
@@ -15616,3 +15616,110 @@ QDF_STATUS sme_set_adaptive_dwelltime_config(tHalHandle hal,
}
return status;
}
+/**
+ * sme_set_pdev_ht_vht_ies() - sends the set pdev IE req
+ * @hal: Pointer to HAL
+ * @enable2x2: 1x1 or 2x2 mode.
+ *
+ * Sends the set pdev IE req with Nss value.
+ *
+ * Return: None
+ */
+void sme_set_pdev_ht_vht_ies(tHalHandle hal, bool enable2x2)
+{
+ tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+ struct sir_set_ht_vht_cfg *ht_vht_cfg;
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+ if (!mac_ctx->per_band_chainmask_supp)
+ return;
+
+ if (!((mac_ctx->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_AUTO) ||
+ (mac_ctx->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11N) ||
+ (mac_ctx->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11N_ONLY) ||
+ (mac_ctx->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11AC) ||
+ (mac_ctx->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11AC_ONLY)))
+ return;
+
+ status = sme_acquire_global_lock(&mac_ctx->sme);
+ if (QDF_STATUS_SUCCESS == status) {
+ ht_vht_cfg = qdf_mem_malloc(sizeof(*ht_vht_cfg));
+ if (NULL == ht_vht_cfg) {
+ sms_log(mac_ctx, LOGE,
+ "%s: mem alloc failed for ht_vht_cfg",
+ __func__);
+ sme_release_global_lock(&mac_ctx->sme);
+ return;
+ }
+
+ ht_vht_cfg->pdev_id = 0;
+ if (enable2x2)
+ ht_vht_cfg->nss = 2;
+ else
+ ht_vht_cfg->nss = 1;
+ ht_vht_cfg->dot11mode =
+ (uint8_t)csr_translate_to_wni_cfg_dot11_mode(mac_ctx,
+ mac_ctx->roam.configParam.uCfgDot11Mode);
+
+ ht_vht_cfg->msg_type = eWNI_SME_PDEV_SET_HT_VHT_IE;
+ ht_vht_cfg->len = sizeof(*ht_vht_cfg);
+ sms_log(mac_ctx, LOG1,
+ FL("SET_HT_VHT_IE with nss %d, dot11mode %d"),
+ ht_vht_cfg->nss,
+ ht_vht_cfg->dot11mode);
+ status = cds_send_mb_message_to_mac(ht_vht_cfg);
+ if (QDF_STATUS_SUCCESS != status) {
+ sms_log(mac_ctx, LOGE, FL(
+ "Send SME_PDEV_SET_HT_VHT_IE fail"));
+ qdf_mem_free(ht_vht_cfg);
+ }
+ sme_release_global_lock(&mac_ctx->sme);
+ }
+ return;
+}
+
+/**
+ * sme_update_vdev_type_nss() - sets the nss per vdev type
+ * @hal: Pointer to HAL
+ * @max_supp_nss: max_supported Nss
+ * @band: 5G or 2.4G band
+ *
+ * Sets the per band Nss for each vdev type based on INI and configured
+ * chain mask value.
+ *
+ * Return: None
+ */
+void sme_update_vdev_type_nss(tHalHandle hal, uint8_t max_supp_nss,
+ uint32_t vdev_type_nss, eCsrBand band)
+{
+ tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+ struct vdev_type_nss *vdev_nss;
+
+ if (eCSR_BAND_5G == band)
+ vdev_nss = &mac_ctx->vdev_type_nss_5g;
+ else
+ vdev_nss = &mac_ctx->vdev_type_nss_2g;
+
+ vdev_nss->sta = QDF_MIN(max_supp_nss, CFG_STA_NSS(vdev_type_nss));
+ vdev_nss->sap = QDF_MIN(max_supp_nss, CFG_SAP_NSS(vdev_type_nss));
+ vdev_nss->p2p_go = QDF_MIN(max_supp_nss,
+ CFG_P2P_GO_NSS(vdev_type_nss));
+ vdev_nss->p2p_cli = QDF_MIN(max_supp_nss,
+ CFG_P2P_CLI_NSS(vdev_type_nss));
+ vdev_nss->p2p_dev = QDF_MIN(max_supp_nss,
+ CFG_P2P_DEV_NSS(vdev_type_nss));
+ vdev_nss->ibss = QDF_MIN(max_supp_nss, CFG_IBSS_NSS(vdev_type_nss));
+ vdev_nss->tdls = QDF_MIN(max_supp_nss, CFG_TDLS_NSS(vdev_type_nss));
+ vdev_nss->ocb = QDF_MIN(max_supp_nss, CFG_OCB_NSS(vdev_type_nss));
+
+ sms_log(mac_ctx, LOG1,
+ "band %d NSS:sta %d sap %d cli %d go %d dev %d ibss %d tdls %d ocb %d",
+ band, vdev_nss->sta, vdev_nss->sap, vdev_nss->p2p_cli,
+ vdev_nss->p2p_go, vdev_nss->p2p_dev, vdev_nss->ibss,
+ vdev_nss->tdls, vdev_nss->ocb);
+}
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index e2a35a7ca335..4de79eb91df9 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -754,6 +754,24 @@ QDF_STATUS csr_update_channel_list(tpAniSirGlobal pMac)
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("Early Stop Scan Feature not supported"));
+ if ((pMac->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_AUTO) ||
+ (pMac->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11AC) ||
+ (pMac->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11AC_ONLY)) {
+ pChanList->vht_en = true;
+ if (pMac->roam.configParam.enableVhtFor24GHz)
+ pChanList->vht_24_en = true;
+ }
+ if ((pMac->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_AUTO) ||
+ (pMac->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11N) ||
+ (pMac->roam.configParam.uCfgDot11Mode ==
+ eCSR_CFG_DOT11_MODE_11N_ONLY)) {
+ pChanList->ht_en = true;
+ }
msg.type = WMA_UPDATE_CHAN_LIST_REQ;
msg.reserved = 0;
msg.bodyptr = pChanList;
@@ -14853,6 +14871,59 @@ QDF_STATUS csr_process_add_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg)
return QDF_STATUS_SUCCESS;
}
+/**
+ * csr_get_vdev_type_nss() - gets the nss value based on vdev type
+ * @mac_ctx: Pointer to Global MAC structure
+ * @dev_mode: current device operating mode.
+ * @nss2g: Pointer to the 2G Nss parameter.
+ * @nss5g: Pointer to the 5G Nss parameter.
+ *
+ * Fills the 2G and 5G Nss values based on device mode.
+ *
+ * Return: None
+ */
+void csr_get_vdev_type_nss(tpAniSirGlobal mac_ctx,
+ enum tQDF_ADAPTER_MODE dev_mode,
+ uint8_t *nss_2g, uint8_t *nss_5g)
+{
+ switch (dev_mode) {
+ case QDF_STA_MODE:
+ *nss_2g = mac_ctx->vdev_type_nss_2g.sta;
+ *nss_5g = mac_ctx->vdev_type_nss_5g.sta;
+ break;
+ case QDF_SAP_MODE:
+ *nss_2g = mac_ctx->vdev_type_nss_2g.sap;
+ *nss_5g = mac_ctx->vdev_type_nss_5g.sap;
+ break;
+ case QDF_P2P_CLIENT_MODE:
+ *nss_2g = mac_ctx->vdev_type_nss_2g.p2p_cli;
+ *nss_5g = mac_ctx->vdev_type_nss_5g.p2p_cli;
+ break;
+ case QDF_P2P_GO_MODE:
+ *nss_2g = mac_ctx->vdev_type_nss_2g.p2p_go;
+ *nss_5g = mac_ctx->vdev_type_nss_5g.p2p_go;
+ break;
+ case QDF_P2P_DEVICE_MODE:
+ *nss_2g = mac_ctx->vdev_type_nss_2g.p2p_dev;
+ *nss_5g = mac_ctx->vdev_type_nss_5g.p2p_dev;
+ break;
+ case QDF_IBSS_MODE:
+ *nss_2g = mac_ctx->vdev_type_nss_2g.ibss;
+ *nss_5g = mac_ctx->vdev_type_nss_5g.ibss;
+ break;
+ case QDF_OCB_MODE:
+ *nss_2g = mac_ctx->vdev_type_nss_2g.ocb;
+ *nss_5g = mac_ctx->vdev_type_nss_5g.ocb;
+ break;
+ default:
+ *nss_2g = 1;
+ *nss_5g = 1;
+ sms_log(mac_ctx, LOGE, FL("Unknown device mode"));
+ break;
+ }
+ sms_log(mac_ctx, LOG1, FL("mode - %d: nss_2g - %d, 5g - %d"),
+ dev_mode, *nss_2g, *nss_5g);
+}
QDF_STATUS csr_issue_add_sta_for_session_req(tpAniSirGlobal pMac, uint32_t sessionId,
tSirMacAddr sessionMacAddr,
uint32_t type, uint32_t subType)
@@ -14888,6 +14959,8 @@ QDF_STATUS csr_process_add_sta_session_command(tpAniSirGlobal pMac,
&pCommand->u.addStaSessionCmd;
uint8_t sessionId = pCommand->sessionId;
struct add_sta_self_params *add_sta_self_req;
+ uint8_t nss_2g;
+ uint8_t nss_5g;
QDF_STATUS status = QDF_STATUS_E_NOMEM;
tSirMsgQ msg;
@@ -14899,12 +14972,16 @@ QDF_STATUS csr_process_add_sta_session_command(tpAniSirGlobal pMac,
return status;
}
+ csr_get_vdev_type_nss(pMac, pAddStaReq->currDeviceMode,
+ &nss_2g, &nss_5g);
qdf_mem_copy(add_sta_self_req->self_mac_addr, pAddStaReq->selfMacAddr,
sizeof(tSirMacAddr));
add_sta_self_req->curr_device_mode = pAddStaReq->currDeviceMode;
add_sta_self_req->session_id = sessionId;
add_sta_self_req->type = pAddStaReq->type;
add_sta_self_req->sub_type = pAddStaReq->subType;
+ add_sta_self_req->nss_2g = nss_2g;
+ add_sta_self_req->nss_5g = nss_5g;
msg.type = WMA_ADD_STA_SELF_REQ;
msg.reserved = 0;
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h
index 153cd68d7356..0850c946a6c8 100644
--- a/core/wma/inc/wma.h
+++ b/core/wma/inc/wma.h
@@ -466,6 +466,28 @@ enum wma_rx_exec_ctx {
WMA_RX_TASKLET_CTX,
WMA_RX_SERIALIZER_CTX
};
+
+/**
+ * enum wma_phy_idx
+ * @PHY1: to notify caller that PHY1 specific param needed
+ * @PHY2: to notify caller that PHY2 specific param needed
+ * @PHY1_PHY2: to notify caller that both PHY's param needed
+ * Note: Firmware sends phy map in terms of bitmask, so enum
+ * also needs to be defined that way.
+ *
+ * For example, 0x3 = 0011 = BIT0 corresponds to one phy and
+ * BIT1 coresponds to another phy. There is no direct relation between
+ * each bit to particular PHY (ex. PHYA or PHYB).
+ *
+ * In simple terms, 3 means referring both PHYs & 1 or 2 means
+ * referring to either PHYA or PHYB.
+ */
+enum wma_phy_idx {
+ PHY1 = 0x1, /* 0x1 */
+ PHY2, /* 0x2 */
+ PHY1_PHY2, /* 0x3 */
+};
+
/**
* struct wma_mem_chunk - memory chunks
* @vaddr: virtual address
@@ -913,6 +935,8 @@ struct wma_txrx_node {
uint32_t mac_id;
bool roaming_in_progress;
int32_t roam_synch_delay;
+ uint8_t nss_2g;
+ uint8_t nss_5g;
};
#if defined(QCA_WIFI_FTM)
@@ -1061,6 +1085,34 @@ struct wma_valid_channels {
uint8_t channel_list[MAX_NUM_CHAN];
};
+/**
+ * struct hw_mode_idx_to_mac_cap_idx - map between hw_mode to capabilities
+ * @num_of_macs: number of macs/PHYs for given hw_mode through hw_mode_id
+ * @mac_cap_idx: index of the mac/PHY for given hw_mode through hw_mode_id
+ * @hw_mode_id: given hw_mode id
+ */
+struct hw_mode_idx_to_mac_cap_idx {
+ uint8_t num_of_macs;
+ uint8_t mac_cap_idx;
+ uint8_t hw_mode_id;
+};
+
+/**
+ * struct extended_caps - new extended caps given by firmware
+ * @num_hw_modes: number of hardware modes for current SOC
+ * @each_hw_mode_cap: hw mode id to phy id mapping
+ * @each_phy_cap_per_hwmode: PHY's caps for each hw mode
+ * @num_phy_for_hal_reg_cap: number of phy for hal reg cap
+ * @hw_mode_to_mac_cap_map: map between hw_mode to capabilities
+ */
+struct extended_caps {
+ WMI_SOC_MAC_PHY_HW_MODE_CAPS num_hw_modes;
+ WMI_HW_MODE_CAPABILITIES *each_hw_mode_cap;
+ WMI_MAC_PHY_CAPABILITIES *each_phy_cap_per_hwmode;
+ WMI_SOC_HAL_REG_CAPABILITIES num_phy_for_hal_reg_cap;
+ WMI_HAL_REG_CAPABILITIES_EXT *each_phy_hal_reg_cap;
+ struct hw_mode_idx_to_mac_cap_idx *hw_mode_to_mac_cap_map;
+};
/**
* struct t_wma_handle - wma context
@@ -1162,6 +1214,7 @@ struct wma_valid_channels {
* @dbs_mode: DBS HW mode list
* @old_hw_mode_index: Previous configured HW mode index
* @new_hw_mode_index: Current configured HW mode index
+ * @extended_caps phy_caps: extended caps per hw mode
* @peer_authorized_cb: peer authorized hdd callback
* @ocb_callback: callback to OCB commands
* @ocb_resp: response to OCB commands
@@ -1322,6 +1375,7 @@ typedef struct {
struct dbs_hw_mode_info hw_mode;
uint32_t old_hw_mode_index;
uint32_t new_hw_mode_index;
+ struct extended_caps phy_caps;
qdf_atomic_t scan_id_counter;
wma_peer_authorized_fp peer_authorized_cb;
uint32_t wow_pno_match_wake_up_count;
@@ -2055,9 +2109,16 @@ QDF_STATUS wma_send_ht40_obss_scanind(tp_wma_handle wma,
int wma_get_bpf_caps_event_handler(void *handle,
u_int8_t *cmd_param_info,
u_int32_t len);
+uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask);
QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma);
QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma,
struct sir_bpf_set_offload *bpf_set_offload);
+void wma_process_set_pdev_ie_req(tp_wma_handle wma,
+ struct set_ie_param *ie_params);
+void wma_process_set_pdev_ht_ie_req(tp_wma_handle wma,
+ struct set_ie_param *ie_params);
+void wma_process_set_pdev_vht_ie_req(tp_wma_handle wma,
+ struct set_ie_param *ie_params);
#endif
struct wma_ini_config *wma_get_ini_handle(tp_wma_handle wma_handle);
WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width,
diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h
index ea7be4ba6d09..1d3cb68d4468 100644
--- a/core/wma/inc/wma_if.h
+++ b/core/wma/inc/wma_if.h
@@ -509,6 +509,8 @@ typedef struct {
uint8_t nonRoamReassoc;
uint8_t wps_state;
uint8_t nss;
+ uint8_t nss_2g;
+ uint8_t nss_5g;
} tAddBssParams, *tpAddBssParams;
/**
@@ -1144,6 +1146,8 @@ typedef struct sMaxTxPowerPerBandParams {
* @type: Vdev Type
* @sub_type: Vdev Sub Type
* @session_id: SME Session ID
+ * @nss_2g: vdev nss in 2.4G
+ * @nss_5g: vdev nss in 5G
* @status: response status code
*/
struct add_sta_self_params {
@@ -1152,9 +1156,32 @@ struct add_sta_self_params {
uint32_t type;
uint32_t sub_type;
uint8_t session_id;
+ uint8_t nss_2g;
+ uint8_t nss_5g;
uint32_t status;
};
+/**
+ * struct set_ie_param - set IE params structure
+ * @pdev_id: pdev id
+ * @ie_type: IE type
+ * @nss: Nss value
+ * @ie_len: IE length
+ * @ie_ptr: Pointer to IE data
+ *
+ * Holds the set pdev IE req data.
+ */
+struct set_ie_param {
+ uint8_t pdev_id;
+ uint8_t ie_type;
+ uint8_t nss;
+ uint8_t ie_len;
+ uint8_t *ie_ptr;
+};
+
+#define DOT11_HT_IE 1
+#define DOT11_VHT_IE 2
+
#ifdef FEATURE_WLAN_TDLS
#define HAL_TDLS_MAX_SUPP_CHANNELS 128
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 3ea0fe060e0c..a62a99cf6127 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -429,6 +429,11 @@ static inline bool wma_is_roam_synch_in_progress(tp_wma_handle wma,
{
return false;
}
+static inline uint32_t wma_roam_scan_get_cckm_mode(
+ struct sSirRoamOffloadScanReq *roam_req, uint32_t auth_mode)
+{
+ return WMI_AUTH_CCKM;
+}
#endif
/*
diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h
index e6a8c86a9f80..0afcf52de27b 100644
--- a/core/wma/inc/wma_tgt_cfg.h
+++ b/core/wma/inc/wma_tgt_cfg.h
@@ -67,6 +67,8 @@ struct wma_tgt_services {
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
bool en_roam_offload;
#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
+ /* per band chain mask support */
+ bool per_band_chainmask_supp;
};
/**
diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h
index 53af2d267a25..3b2120ed9ee6 100644
--- a/core/wma/inc/wma_types.h
+++ b/core/wma/inc/wma_types.h
@@ -472,9 +472,10 @@
#define WMA_REMOVE_BCN_FILTER_CMDID SIR_HAL_REMOVE_BCN_FILTER_CMDID
#define WMA_SET_ADAPT_DWELLTIME_CONF_PARAMS SIR_HAL_SET_ADAPT_DWELLTIME_PARAMS
-#define WDA_BPF_GET_CAPABILITIES_REQ SIR_HAL_BPF_GET_CAPABILITIES_REQ
-#define WDA_BPF_SET_INSTRUCTIONS_REQ SIR_HAL_BPF_SET_INSTRUCTIONS_REQ
+#define WDA_BPF_GET_CAPABILITIES_REQ SIR_HAL_BPF_GET_CAPABILITIES_REQ
+#define WDA_BPF_SET_INSTRUCTIONS_REQ SIR_HAL_BPF_SET_INSTRUCTIONS_REQ
+#define WMA_SET_PDEV_IE_REQ SIR_HAL_SET_PDEV_IE_REQ
/* Bit 6 will be used to control BD rate for Management frames */
#define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40
diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c
index d7040f577fca..e5fb871525a5 100644
--- a/core/wma/src/wma_dev_if.c
+++ b/core/wma/src/wma_dev_if.c
@@ -1485,6 +1485,8 @@ ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle,
params.if_id = self_sta_req->session_id;
params.type = self_sta_req->type;
params.subtype = self_sta_req->sub_type;
+ params.nss_2g = self_sta_req->nss_2g;
+ params.nss_5g = self_sta_req->nss_5g;
/* Create a vdev in target */
status = wmi_unified_vdev_create_send(wma_handle->wmi_handle,
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index d73b338bdb2b..6d96bf91e3de 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -3051,7 +3051,7 @@ static QDF_STATUS wma_add_wow_wakeup_event(tp_wma_handle wma,
int ret;
ret = wmi_unified_add_wow_wakeup_event_cmd(wma->wmi_handle, vdev_id,
- enable, bitmap);
+ bitmap, enable);
if (ret) {
WMA_LOGE("Failed to config wow wakeup event");
return QDF_STATUS_E_FAILURE;
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index da68b5df928c..a62af7827aa0 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -3112,6 +3112,46 @@ QDF_STATUS wma_wmi_work_close(void *cds_ctx)
return QDF_STATUS_SUCCESS;
}
+/**
+ * wma_cleanup_dbs_phy_caps() - release memory allocated for holding ext cap
+ * @wma_handle: pointer to wma handle
+ *
+ * This function releases all the memory created for holding extended
+ * capabilities per hardware mode and per PHY
+ *
+ * Return: void
+ */
+static void wma_cleanup_dbs_phy_caps(t_wma_handle *wma_handle)
+{
+ if (NULL == wma_handle) {
+ WMA_LOGE("%s: Invalid wma handle", __func__);
+ return;
+ }
+
+ if (wma_handle->phy_caps.hw_mode_to_mac_cap_map) {
+ qdf_mem_free(wma_handle->phy_caps.hw_mode_to_mac_cap_map);
+ wma_handle->phy_caps.hw_mode_to_mac_cap_map = NULL;
+ WMA_LOGI("%s: hw_mode_to_mac_cap_map freed", __func__);
+ }
+
+ if (wma_handle->phy_caps.each_hw_mode_cap) {
+ qdf_mem_free(wma_handle->phy_caps.each_hw_mode_cap);
+ wma_handle->phy_caps.each_hw_mode_cap = NULL;
+ WMA_LOGI("%s: each_hw_mode_cap freed", __func__);
+ }
+
+ if (wma_handle->phy_caps.each_phy_cap_per_hwmode) {
+ qdf_mem_free(wma_handle->phy_caps.each_phy_cap_per_hwmode);
+ wma_handle->phy_caps.each_phy_cap_per_hwmode = NULL;
+ WMA_LOGI("%s: each_phy_cap_per_hwmode freed", __func__);
+ }
+
+ if (wma_handle->phy_caps.each_phy_hal_reg_cap) {
+ qdf_mem_free(wma_handle->phy_caps.each_phy_hal_reg_cap);
+ wma_handle->phy_caps.each_phy_hal_reg_cap = NULL;
+ WMA_LOGI("%s: each_phy_hal_reg_cap freed", __func__);
+ }
+}
/**
* wma_close() - wma close function.
@@ -3148,7 +3188,7 @@ QDF_STATUS wma_close(void *cds_ctx)
wma_handle->hw_mode.hw_mode_list = NULL;
WMA_LOGI("%s: DBS list is freed", __func__);
}
-
+ wma_cleanup_dbs_phy_caps(wma_handle);
if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
#ifdef FEATURE_WLAN_SCAN_PNO
qdf_wake_lock_destroy(&wma_handle->pno_wake_lock);
@@ -3397,6 +3437,9 @@ static inline void wma_update_target_services(tp_wma_handle wh,
cfg->en_tdls_uapsd_sleep_sta =
WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap,
WMI_SERVICE_TDLS_UAPSD_SLEEP_STA);
+ cfg->per_band_chainmask_supp =
+ WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap,
+ WMI_SERVICE_PER_BAND_CHAINMASK_SUPPORT);
#endif /* FEATURE_WLAN_TDLS */
if (WMI_SERVICE_IS_ENABLED
(wh->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD))
@@ -3519,6 +3562,301 @@ static inline void wma_update_target_vht_cap(tp_wma_handle wh,
}
/**
+ * wma_derive_ext_ht_cap() - Derive HT caps based on given value
+ * @wma_handle: pointer to wma_handle
+ * @ht_cap: given pointer to HT caps which needs to be updated
+ * @tx_chain: given tx chainmask value
+ * @rx_chain: given rx chainmask value
+ * @value: new HT cap info provided in form of bitmask
+ *
+ * This function takes the value provided in form of bitmask and decodes
+ * it. After decoding, what ever value it gets, it takes the union(max) or
+ * intersection(min) with previously derived values.
+ *
+ * Return: none
+ *
+ */
+static void wma_derive_ext_ht_cap(tp_wma_handle wma_handle,
+ struct wma_tgt_ht_cap *ht_cap, uint32_t value,
+ uint32_t tx_chain, uint32_t rx_chain)
+{
+ struct wma_tgt_ht_cap tmp = {0};
+
+ if (NULL == wma_handle || NULL == ht_cap)
+ return;
+
+ if (0 == qdf_mem_cmp(ht_cap, &tmp, sizeof(struct wma_tgt_ht_cap))) {
+ ht_cap->ht_rx_stbc = (!!(value & WMI_HT_CAP_RX_STBC));
+ ht_cap->ht_tx_stbc = (!!(value & WMI_HT_CAP_TX_STBC));
+ ht_cap->mpdu_density = (!!(value & WMI_HT_CAP_MPDU_DENSITY));
+ ht_cap->ht_rx_ldpc = (!!(value & WMI_HT_CAP_RX_LDPC));
+ ht_cap->ht_sgi_20 = (!!(value & WMI_HT_CAP_HT20_SGI));
+ ht_cap->ht_sgi_40 = (!!(value & WMI_HT_CAP_HT40_SGI));
+ ht_cap->num_rf_chains =
+ QDF_MAX(wma_get_num_of_setbits_from_bitmask(tx_chain),
+ wma_get_num_of_setbits_from_bitmask(rx_chain));
+ } else {
+ ht_cap->ht_rx_stbc = QDF_MIN(ht_cap->ht_rx_stbc,
+ (!!(value & WMI_HT_CAP_RX_STBC)));
+ ht_cap->ht_tx_stbc = QDF_MAX(ht_cap->ht_tx_stbc,
+ (!!(value & WMI_HT_CAP_TX_STBC)));
+ ht_cap->mpdu_density = QDF_MIN(ht_cap->mpdu_density,
+ (!!(value & WMI_HT_CAP_MPDU_DENSITY)));
+ ht_cap->ht_rx_ldpc = QDF_MIN(ht_cap->ht_rx_ldpc,
+ (!!(value & WMI_HT_CAP_RX_LDPC)));
+ ht_cap->ht_sgi_20 = QDF_MIN(ht_cap->ht_sgi_20,
+ (!!(value & WMI_HT_CAP_HT20_SGI)));
+ ht_cap->ht_sgi_40 = QDF_MIN(ht_cap->ht_sgi_40,
+ (!!(value & WMI_HT_CAP_HT40_SGI)));
+ ht_cap->num_rf_chains =
+ QDF_MAX(ht_cap->num_rf_chains,
+ QDF_MAX(wma_get_num_of_setbits_from_bitmask(
+ tx_chain),
+ wma_get_num_of_setbits_from_bitmask(
+ rx_chain)));
+ }
+}
+
+/**
+ * wma_update_target_ext_ht_cap() - Update HT caps with given extended cap
+ * @wma_handle: pointer to wma_handle
+ * @ht_cap: HT cap structure to be filled
+ *
+ * This function loop through each hardware mode and for each hardware mode
+ * again it loop through each MAC/PHY and pull the caps 2G and 5G specific
+ * HT caps and derives the final cap.
+ *
+ * Return: none
+ *
+ */
+static void wma_update_target_ext_ht_cap(tp_wma_handle wma_handle,
+ struct wma_tgt_ht_cap *ht_cap)
+{
+ int i, j = 0, max_mac;
+ uint32_t ht_2g, ht_5g;
+ struct wma_tgt_ht_cap tmp_ht_cap = {0}, tmp_cap = {0};
+ struct extended_caps *phy_caps;
+ WMI_MAC_PHY_CAPABILITIES *mac_cap;
+
+ /*
+ * for legacy device extended cap might not even come, so in that case
+ * don't overwrite legacy values
+ */
+ if (!wma_handle ||
+ (0 == wma_handle->phy_caps.num_hw_modes.num_hw_modes)) {
+ WMA_LOGI("%s: No extended HT cap for current SOC", __func__);
+ return;
+ }
+
+ phy_caps = &wma_handle->phy_caps;
+ for (i = 0; i < phy_caps->num_hw_modes.num_hw_modes; i++) {
+ if (phy_caps->each_hw_mode_cap[i].phy_id_map == PHY1_PHY2)
+ max_mac = j + 2;
+ else
+ max_mac = j + 1;
+ for ( ; j < max_mac; j++) {
+ mac_cap = &phy_caps->each_phy_cap_per_hwmode[j];
+ ht_2g = mac_cap->ht_cap_info_2G;
+ ht_5g = mac_cap->ht_cap_info_5G;
+ if (ht_2g)
+ wma_derive_ext_ht_cap(wma_handle, &tmp_ht_cap,
+ ht_2g, mac_cap->tx_chain_mask_2G,
+ mac_cap->rx_chain_mask_2G);
+ if (ht_5g)
+ wma_derive_ext_ht_cap(wma_handle, &tmp_ht_cap,
+ ht_5g, mac_cap->tx_chain_mask_5G,
+ mac_cap->rx_chain_mask_5G);
+ }
+ }
+
+ if (0 != qdf_mem_cmp(&tmp_cap, &tmp_ht_cap,
+ sizeof(struct wma_tgt_ht_cap))) {
+ qdf_mem_copy(ht_cap, &tmp_ht_cap,
+ sizeof(struct wma_tgt_ht_cap));
+ }
+
+ WMA_LOGI("%s: [ext ht cap] ht_rx_stbc - %d, ht_tx_stbc - %d\n\
+ mpdu_density - %d ht_rx_ldpc - %d ht_sgi_20 - %d\n\
+ ht_sgi_40 - %d num_rf_chains - %d ", __func__,
+ ht_cap->ht_rx_stbc, ht_cap->ht_tx_stbc,
+ ht_cap->mpdu_density, ht_cap->ht_rx_ldpc,
+ ht_cap->ht_sgi_20, ht_cap->ht_sgi_40,
+ ht_cap->num_rf_chains);
+}
+
+/**
+ * wma_derive_ext_vht_cap() - Derive VHT caps based on given value
+ * @wma_handle: pointer to wma_handle
+ * @vht_cap: pointer to given VHT caps to be filled
+ * @value: new VHT cap info provided in form of bitmask
+ *
+ * This function takes the value provided in form of bitmask and decodes
+ * it. After decoding, what ever value it gets, it takes the union(max) or
+ * intersection(min) with previously derived values.
+ *
+ * Return: none
+ *
+ */
+static void wma_derive_ext_vht_cap(t_wma_handle *wma_handle,
+ struct wma_tgt_vht_cap *vht_cap, uint32_t value)
+{
+ struct wma_tgt_vht_cap tmp_cap = {0};
+ uint32_t tmp = 0;
+
+ if (NULL == wma_handle || NULL == vht_cap)
+ return;
+
+ if (0 == qdf_mem_cmp(vht_cap, &tmp_cap,
+ sizeof(struct wma_tgt_vht_cap))) {
+ if (value & WMI_VHT_CAP_MAX_MPDU_LEN_11454)
+ vht_cap->vht_max_mpdu = WMI_VHT_CAP_MAX_MPDU_LEN_11454;
+ else if (value & WMI_VHT_CAP_MAX_MPDU_LEN_7935)
+ vht_cap->vht_max_mpdu = WMI_VHT_CAP_MAX_MPDU_LEN_7935;
+ else
+ vht_cap->vht_max_mpdu = 0;
+
+ if (value & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ) {
+ vht_cap->supp_chan_width =
+ 1 << eHT_CHANNEL_WIDTH_80P80MHZ;
+ vht_cap->supp_chan_width |=
+ 1 << eHT_CHANNEL_WIDTH_160MHZ;
+ } else if (value & WMI_VHT_CAP_CH_WIDTH_160MHZ) {
+ vht_cap->supp_chan_width =
+ 1 << eHT_CHANNEL_WIDTH_160MHZ;
+ } else {
+ vht_cap->supp_chan_width = 1 << eHT_CHANNEL_WIDTH_80MHZ;
+ }
+ vht_cap->vht_rx_ldpc = value & WMI_VHT_CAP_RX_LDPC;
+ vht_cap->vht_short_gi_80 = value & WMI_VHT_CAP_SGI_80MHZ;
+ vht_cap->vht_short_gi_160 = value & WMI_VHT_CAP_SGI_160MHZ;
+ vht_cap->vht_tx_stbc = value & WMI_VHT_CAP_TX_STBC;
+ vht_cap->vht_rx_stbc =
+ (value & WMI_VHT_CAP_RX_STBC_1SS) |
+ (value & WMI_VHT_CAP_RX_STBC_2SS) |
+ (value & WMI_VHT_CAP_RX_STBC_3SS);
+ vht_cap->vht_max_ampdu_len_exp =
+ (value & WMI_VHT_CAP_MAX_AMPDU_LEN_EXP) >>
+ WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT;
+ vht_cap->vht_su_bformer = value & WMI_VHT_CAP_SU_BFORMER;
+ vht_cap->vht_su_bformee = value & WMI_VHT_CAP_SU_BFORMEE;
+ vht_cap->vht_mu_bformer = value & WMI_VHT_CAP_MU_BFORMER;
+ vht_cap->vht_mu_bformee = value & WMI_VHT_CAP_MU_BFORMEE;
+ vht_cap->vht_txop_ps = value & WMI_VHT_CAP_TXOP_PS;
+ } else {
+ if (value & WMI_VHT_CAP_MAX_MPDU_LEN_11454)
+ tmp = WMI_VHT_CAP_MAX_MPDU_LEN_11454;
+ else if (value & WMI_VHT_CAP_MAX_MPDU_LEN_7935)
+ tmp = WMI_VHT_CAP_MAX_MPDU_LEN_7935;
+ else
+ tmp = 0;
+ vht_cap->vht_max_mpdu = QDF_MIN(vht_cap->vht_max_mpdu, tmp);
+
+ if ((value & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)) {
+ tmp = (1 << eHT_CHANNEL_WIDTH_80P80MHZ) |
+ (1 << eHT_CHANNEL_WIDTH_160MHZ);
+ } else if (value & WMI_VHT_CAP_CH_WIDTH_160MHZ) {
+ tmp = 1 << eHT_CHANNEL_WIDTH_160MHZ;
+ } else {
+ tmp = 1 << eHT_CHANNEL_WIDTH_80MHZ;
+ }
+ vht_cap->supp_chan_width =
+ QDF_MAX(vht_cap->supp_chan_width, tmp);
+ vht_cap->vht_rx_ldpc = QDF_MIN(vht_cap->vht_rx_ldpc,
+ value & WMI_VHT_CAP_RX_LDPC);
+ vht_cap->vht_short_gi_80 = QDF_MAX(vht_cap->vht_short_gi_80,
+ value & WMI_VHT_CAP_SGI_80MHZ);
+ vht_cap->vht_short_gi_160 = QDF_MAX(vht_cap->vht_short_gi_160,
+ value & WMI_VHT_CAP_SGI_160MHZ);
+ vht_cap->vht_tx_stbc = QDF_MAX(vht_cap->vht_tx_stbc,
+ value & WMI_VHT_CAP_TX_STBC);
+ vht_cap->vht_rx_stbc = QDF_MIN(vht_cap->vht_rx_stbc,
+ (value & WMI_VHT_CAP_RX_STBC_1SS) |
+ (value & WMI_VHT_CAP_RX_STBC_2SS) |
+ (value & WMI_VHT_CAP_RX_STBC_3SS));
+ vht_cap->vht_max_ampdu_len_exp =
+ QDF_MIN(vht_cap->vht_max_ampdu_len_exp,
+ (value & WMI_VHT_CAP_MAX_AMPDU_LEN_EXP) >>
+ WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT);
+ vht_cap->vht_su_bformer = QDF_MAX(vht_cap->vht_su_bformer,
+ value & WMI_VHT_CAP_SU_BFORMER);
+ vht_cap->vht_su_bformee = QDF_MAX(vht_cap->vht_su_bformee,
+ value & WMI_VHT_CAP_SU_BFORMEE);
+ vht_cap->vht_mu_bformer = QDF_MAX(vht_cap->vht_mu_bformer,
+ value & WMI_VHT_CAP_MU_BFORMER);
+ vht_cap->vht_mu_bformee = QDF_MAX(vht_cap->vht_mu_bformee,
+ value & WMI_VHT_CAP_MU_BFORMEE);
+ vht_cap->vht_txop_ps = QDF_MIN(vht_cap->vht_txop_ps,
+ value & WMI_VHT_CAP_TXOP_PS);
+ }
+}
+
+/**
+ * wma_update_target_ext_vht_cap() - Update VHT caps with given extended cap
+ * @wma_handle: pointer to wma_handle
+ * @vht_cap: VHT cap structure to be filled
+ *
+ * This function loop through each hardware mode and for each hardware mode
+ * again it loop through each MAC/PHY and pull the caps 2G and 5G specific
+ * VHT caps and derives the final cap.
+ *
+ * Return: none
+ *
+ */
+static void wma_update_target_ext_vht_cap(t_wma_handle *wma_handle,
+ struct wma_tgt_vht_cap *vht_cap)
+{
+ int i, j = 0, max_mac;
+ uint32_t vht_cap_info_2g, vht_cap_info_5g;
+ struct wma_tgt_vht_cap tmp_vht_cap = {0}, tmp_cap = {0};
+ struct extended_caps *phy_caps;
+ WMI_MAC_PHY_CAPABILITIES *mac_cap;
+
+ /*
+ * for legacy device extended cap might not even come, so in that case
+ * don't overwrite legacy values
+ */
+ if (!wma_handle ||
+ (0 == wma_handle->phy_caps.num_hw_modes.num_hw_modes)) {
+ WMA_LOGI("%s: No extended VHT cap for current SOC", __func__);
+ return;
+ }
+
+ phy_caps = &wma_handle->phy_caps;
+ for (i = 0; i < phy_caps->num_hw_modes.num_hw_modes; i++) {
+ if (phy_caps->each_hw_mode_cap[i].phy_id_map == PHY1_PHY2)
+ max_mac = j + 2;
+ else
+ max_mac = j + 1;
+ for ( ; j < max_mac; j++) {
+ mac_cap = &phy_caps->each_phy_cap_per_hwmode[j];
+ vht_cap_info_2g = mac_cap->vht_cap_info_2G;
+ vht_cap_info_5g = mac_cap->vht_cap_info_5G;
+ if (vht_cap_info_2g)
+ wma_derive_ext_vht_cap(wma_handle, &tmp_vht_cap,
+ vht_cap_info_2g);
+ if (vht_cap_info_5g)
+ wma_derive_ext_vht_cap(wma_handle, &tmp_vht_cap,
+ vht_cap_info_5g);
+ }
+ }
+
+ if (0 != qdf_mem_cmp(&tmp_cap, &tmp_vht_cap,
+ sizeof(struct wma_tgt_vht_cap))) {
+ qdf_mem_copy(vht_cap, &tmp_vht_cap,
+ sizeof(struct wma_tgt_vht_cap));
+ }
+
+ WMA_LOGI("%s: [ext vhtcap] max_mpdu %d supp_chan_width %x rx_ldpc %x\n \
+ short_gi_80 %x tx_stbc %x rx_stbc %x txop_ps %x\n \
+ su_bformee %x mu_bformee %x max_ampdu_len_exp %d", __func__,
+ vht_cap->vht_max_mpdu, vht_cap->supp_chan_width,
+ vht_cap->vht_rx_ldpc, vht_cap->vht_short_gi_80,
+ vht_cap->vht_tx_stbc, vht_cap->vht_rx_stbc,
+ vht_cap->vht_txop_ps, vht_cap->vht_su_bformee,
+ vht_cap->vht_mu_bformee, vht_cap->vht_max_ampdu_len_exp);
+}
+
+/**
* wma_update_hdd_cfg() - update HDD config
* @wma_handle: wma handle
*
@@ -3557,6 +3895,12 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle)
wma_update_target_services(wma_handle, &tgt_cfg.services);
wma_update_target_ht_cap(wma_handle, &tgt_cfg.ht_cap);
wma_update_target_vht_cap(wma_handle, &tgt_cfg.vht_cap);
+ /*
+ * This will overwrite the structure filled by wma_update_target_ht_cap
+ * and wma_update_target_vht_cap APIs.
+ */
+ wma_update_target_ext_ht_cap(wma_handle, &tgt_cfg.ht_cap);
+ wma_update_target_ext_vht_cap(wma_handle, &tgt_cfg.vht_cap);
tgt_cfg.target_fw_version = wma_handle->target_fw_version;
#ifdef WLAN_FEATURE_LPSS
@@ -4047,6 +4391,225 @@ int wma_rx_service_ready_event(void *handle, uint8_t *cmd_param_info,
}
/**
+ * wma_print_populate_soc_caps() - Prints all the caps populated per hw mode
+ * @wma_handle: pointer to wma_handle
+ *
+ * This function prints all the caps populater per hw mode and per PHY
+ *
+ * Return: none
+ */
+static void wma_print_populate_soc_caps(t_wma_handle *wma_handle)
+{
+ int i, j = 0, max_mac;
+ WMI_MAC_PHY_CAPABILITIES *tmp;
+
+ /* print number of hw modes */
+ WMA_LOGI("%s: num of hw modes [%d]", __func__,
+ wma_handle->phy_caps.num_hw_modes.num_hw_modes);
+ WMA_LOGI("%s: <====== HW mode cap printing starts ======>", __func__);
+ /* print cap of each hw mode */
+ for (i = 0; i < wma_handle->phy_caps.num_hw_modes.num_hw_modes; i++) {
+ WMA_LOGI("====>: hw mode id[%d], phy_id map[%d]",
+ wma_handle->phy_caps.each_hw_mode_cap[i].hw_mode_id,
+ wma_handle->phy_caps.each_hw_mode_cap[i].phy_id_map);
+ if (wma_handle->phy_caps.each_hw_mode_cap[i].phy_id_map ==
+ PHY1_PHY2)
+ max_mac = j + 2;
+ else
+ max_mac = j + 1;
+
+ for ( ; j < max_mac; j++) {
+ tmp = &wma_handle->phy_caps.each_phy_cap_per_hwmode[j];
+ WMA_LOGI("\t: index j[%d]", j);
+ WMA_LOGI("\t: cap for hw_mode_id[%d]", tmp->hw_mode_id);
+ WMA_LOGI("\t: pdev_id[%d]", tmp->pdev_id);
+ WMA_LOGI("\t: phy_id[%d]", tmp->phy_id);
+ WMA_LOGI("\t: supports_11b[%d]",
+ WMI_SUPPORT_11B_GET(tmp->supported_flags));
+ WMA_LOGI("\t: supports_11g[%d]",
+ WMI_SUPPORT_11G_GET(tmp->supported_flags));
+ WMA_LOGI("\t: supports_11a[%d]",
+ WMI_SUPPORT_11A_GET(tmp->supported_flags));
+ WMA_LOGI("\t: supports_11n[%d]",
+ WMI_SUPPORT_11N_GET(tmp->supported_flags));
+ WMA_LOGI("\t: supports_11ac[%d]",
+ WMI_SUPPORT_11AC_GET(tmp->supported_flags));
+ WMA_LOGI("\t: supports_11ax[%d]",
+ WMI_SUPPORT_11AX_GET(tmp->supported_flags));
+ WMA_LOGI("\t: supported_flags[%d]",
+ tmp->supported_flags);
+ WMA_LOGI("\t: supported_bands[%d]",
+ tmp->supported_bands);
+ WMA_LOGI("\t: ampdu_density[%d]",
+ tmp->ampdu_density);
+ WMA_LOGI("\t: max_bw_supported_2G[%d]",
+ tmp->max_bw_supported_2G);
+ WMA_LOGI("\t: ht_cap_info_2G[%d]", tmp->ht_cap_info_2G);
+ WMA_LOGI("\t: vht_cap_info_2G[%d]",
+ tmp->vht_cap_info_2G);
+ WMA_LOGI("\t: he_cap_info_2G[%d]", tmp->he_cap_info_2G);
+ WMA_LOGI("\t: vht_supp_mcs_2G[%d]",
+ tmp->vht_supp_mcs_2G);
+ WMA_LOGI("\t: he_supp_mcs_2G[%d]", tmp->he_supp_mcs_2G);
+ WMA_LOGI("\t: tx_chain_mask_2G[%d]",
+ tmp->tx_chain_mask_2G);
+ WMA_LOGI("\t: rx_chain_mask_2G[%d]",
+ tmp->rx_chain_mask_2G);
+ WMA_LOGI("\t: max_bw_supported_5G[%d]",
+ tmp->max_bw_supported_5G);
+ WMA_LOGI("\t: ht_cap_info_5G[%d]",
+ tmp->ht_cap_info_5G);
+ WMA_LOGI("\t: vht_cap_info_5G[%d]",
+ tmp->vht_cap_info_5G);
+ WMA_LOGI("\t: he_cap_info_5G[%d]", tmp->he_cap_info_5G);
+ WMA_LOGI("\t: vht_supp_mcs_5G[%d]",
+ tmp->vht_supp_mcs_5G);
+ WMA_LOGI("\t: he_supp_mcs_5G[%d]", tmp->he_supp_mcs_5G);
+ WMA_LOGI("\t: tx_chain_mask_5G[%d]",
+ tmp->tx_chain_mask_5G);
+ WMA_LOGI("\t: rx_chain_mask_5G[%d]",
+ tmp->rx_chain_mask_5G);
+ }
+ }
+ WMA_LOGI("%s: <====== HW mode cap printing ends ======>\n", __func__);
+}
+
+/**
+ * wma_populate_soc_caps() - populate entire SOC's capabilities
+ * @wma_handle: pointer to wma global structure
+ * @param_buf: pointer to param of service ready extension event from fw
+ *
+ * This API populates all capabilities of entire SOC. For example,
+ * how many number of hw modes are supported by this SOC, what are the
+ * capabilities of each phy per hw mode, what are HAL reg capabilities per
+ * phy.
+ *
+ * Return: none
+ */
+static void wma_populate_soc_caps(t_wma_handle *wma_handle,
+ WMI_SERVICE_READY_EXT_EVENTID_param_tlvs *param_buf)
+{
+ int i, num_of_mac_caps = 0, tmp = 0;
+ struct extended_caps *phy_caps;
+ struct hw_mode_idx_to_mac_cap_idx *map;
+
+ WMA_LOGD("%s: Enter", __func__);
+
+ if (!wma_handle) {
+ WMA_LOGP("%s: Invalid WMA handle", __func__);
+ return;
+ }
+
+ if (!param_buf) {
+ WMA_LOGP("%s: Invalid event", __func__);
+ return;
+ }
+ phy_caps = &wma_handle->phy_caps;
+
+ /*
+ * first thing to do is to get how many number of hw modes are
+ * supported and populate in wma_handle global structure
+ */
+ qdf_mem_copy(&phy_caps->num_hw_modes,
+ param_buf->soc_hw_mode_caps,
+ sizeof(WMI_SOC_MAC_PHY_HW_MODE_CAPS));
+ if (0 == phy_caps->num_hw_modes.num_hw_modes) {
+ WMA_LOGE("%s: Invalid number of hw modes", __func__);
+ return;
+ } else {
+ WMA_LOGI("%s: Given number of hw modes[%d]",
+ __func__, phy_caps->num_hw_modes.num_hw_modes);
+ }
+
+ /*
+ * next thing is to allocate the memory to map hw mode to phy/mac caps
+ */
+ phy_caps->hw_mode_to_mac_cap_map =
+ qdf_mem_malloc(phy_caps->num_hw_modes.num_hw_modes *
+ sizeof(struct hw_mode_idx_to_mac_cap_idx));
+ if (!phy_caps->hw_mode_to_mac_cap_map) {
+ WMA_LOGE("%s: Memory allocation failed", __func__);
+ return;
+ }
+
+ /*
+ * next thing is to allocate the memory for per hw caps
+ */
+ phy_caps->each_hw_mode_cap =
+ qdf_mem_malloc(phy_caps->num_hw_modes.num_hw_modes *
+ sizeof(WMI_HW_MODE_CAPABILITIES));
+ if (!phy_caps->each_hw_mode_cap) {
+ WMA_LOGE("%s: Memory allocation failed", __func__);
+ wma_cleanup_dbs_phy_caps(wma_handle);
+ return;
+ }
+ qdf_mem_copy(phy_caps->each_hw_mode_cap,
+ param_buf->hw_mode_caps,
+ phy_caps->num_hw_modes.num_hw_modes *
+ sizeof(WMI_HW_MODE_CAPABILITIES));
+ /*
+ * next thing is to count the number of mac cap to populate per
+ * hw mode and generate map, so that our search can be done
+ * efficiently which is O(1)
+ */
+ for (i = 0; i < phy_caps->num_hw_modes.num_hw_modes; i++) {
+ map = &phy_caps->hw_mode_to_mac_cap_map[i];
+ if (phy_caps->each_hw_mode_cap[i].phy_id_map == PHY1_PHY2) {
+ tmp = num_of_mac_caps;
+ num_of_mac_caps = num_of_mac_caps + 2;
+ map->num_of_macs = 2;
+ } else {
+ tmp = num_of_mac_caps;
+ num_of_mac_caps = num_of_mac_caps + 1;
+ map->num_of_macs = 1;
+ }
+ map->mac_cap_idx = tmp;
+ map->hw_mode_id = phy_caps->each_hw_mode_cap[i].hw_mode_id;
+ }
+
+ /*
+ * next thing is to populate each phy caps per hw mode
+ */
+ phy_caps->each_phy_cap_per_hwmode =
+ qdf_mem_malloc(num_of_mac_caps *
+ sizeof(WMI_MAC_PHY_CAPABILITIES));
+ if (!phy_caps->each_phy_cap_per_hwmode) {
+ WMA_LOGE("%s: Memory allocation failed", __func__);
+ wma_cleanup_dbs_phy_caps(wma_handle);
+ return;
+ }
+ qdf_mem_copy(phy_caps->each_phy_cap_per_hwmode,
+ param_buf->mac_phy_caps,
+ num_of_mac_caps * sizeof(WMI_MAC_PHY_CAPABILITIES));
+
+ /*
+ * next thing is to populate reg caps per phy
+ */
+ qdf_mem_copy(&phy_caps->num_phy_for_hal_reg_cap,
+ param_buf->soc_hal_reg_caps,
+ sizeof(WMI_SOC_HAL_REG_CAPABILITIES));
+ if (phy_caps->num_phy_for_hal_reg_cap.num_phy == 0) {
+ WMA_LOGE("%s: incorrect number of phys", __func__);
+ wma_cleanup_dbs_phy_caps(wma_handle);
+ return;
+ }
+ phy_caps->each_phy_hal_reg_cap =
+ qdf_mem_malloc(phy_caps->num_phy_for_hal_reg_cap.num_phy *
+ sizeof(WMI_HAL_REG_CAPABILITIES_EXT));
+ if (!phy_caps->each_phy_hal_reg_cap) {
+ WMA_LOGE("%s: Memory allocation failed", __func__);
+ wma_cleanup_dbs_phy_caps(wma_handle);
+ return;
+ }
+ qdf_mem_copy(phy_caps->each_phy_hal_reg_cap,
+ param_buf->hal_reg_caps,
+ phy_caps->num_phy_for_hal_reg_cap.num_phy *
+ sizeof(WMI_HAL_REG_CAPABILITIES_EXT));
+ wma_print_populate_soc_caps(wma_handle);
+ return;
+}
+
+/**
* wma_rx_service_ready_ext_event() - evt handler for sevice ready ext event.
* @handle: wma handle
* @event: params of the service ready extended event
@@ -4093,6 +4656,7 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event,
WMA_LOGP("Failed to stop the service ready ext timer");
return -EINVAL;
}
+ wma_populate_soc_caps(wma_handle, param_buf);
WMA_LOGA("WMA --> WMI_INIT_CMDID");
status = wmi_unified_send_saved_init_cmd(wma_handle->wmi_handle);
@@ -4710,6 +5274,11 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
(wma_cli_set_cmd_t *) msg->bodyptr);
qdf_mem_free(msg->bodyptr);
break;
+ case WMA_SET_PDEV_IE_REQ:
+ wma_process_set_pdev_ie_req(wma_handle,
+ (struct set_ie_param *)msg->bodyptr);
+ qdf_mem_free(msg->bodyptr);
+ break;
#if !defined(REMOVE_PKT_LOG)
case WMA_PKTLOG_ENABLE_REQ:
wma_pktlog_wmi_send_cmd(wma_handle,
diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c
index 6bab3975213e..b581f2fd8cf5 100644
--- a/core/wma/src/wma_scan_roam.c
+++ b/core/wma/src/wma_scan_roam.c
@@ -649,6 +649,8 @@ QDF_STATUS wma_update_channel_list(WMA_HANDLE handle,
tchan_info = scan_ch_param.chan_info;
scan_ch_param.num_scan_chans = chan_list->numChan;
wma_handle->saved_chan.num_channels = chan_list->numChan;
+ WMA_LOGD("ht %d, vht %d, vht_24 %d", chan_list->ht_en,
+ chan_list->vht_en, chan_list->vht_24_en);
for (i = 0; i < chan_list->numChan; ++i) {
tchan_info->mhz =
@@ -668,10 +670,21 @@ QDF_STATUS wma_update_channel_list(WMA_HANDLE handle,
chan_list->chanParam[i].dfsSet);
}
- if (tchan_info->mhz < WMA_2_4_GHZ_MAX_FREQ)
+ if (tchan_info->mhz < WMA_2_4_GHZ_MAX_FREQ) {
WMI_SET_CHANNEL_MODE(tchan_info, MODE_11G);
- else
+ if (chan_list->vht_en && chan_list->vht_24_en)
+ WMI_SET_CHANNEL_FLAG(tchan_info,
+ WMI_CHAN_FLAG_ALLOW_VHT);
+ } else {
WMI_SET_CHANNEL_MODE(tchan_info, MODE_11A);
+ if (chan_list->vht_en)
+ WMI_SET_CHANNEL_FLAG(tchan_info,
+ WMI_CHAN_FLAG_ALLOW_VHT);
+ }
+
+ if (chan_list->ht_en)
+ WMI_SET_CHANNEL_FLAG(tchan_info,
+ WMI_CHAN_FLAG_ALLOW_HT);
if (chan_list->chanParam[i].half_rate)
WMI_SET_CHANNEL_FLAG(tchan_info,
@@ -1017,8 +1030,9 @@ A_UINT32 e_csr_auth_type_to_rsn_authmode(eCsrAuthType authtype,
#endif /* FEATURE_WLAN_WAPI */
#ifdef FEATURE_WLAN_ESE
case eCSR_AUTH_TYPE_CCKM_WPA:
+ return WMI_AUTH_CCKM_WPA;
case eCSR_AUTH_TYPE_CCKM_RSN:
- return WMI_AUTH_CCKM;
+ return WMI_AUTH_CCKM_RSNA;
#endif /* FEATURE_WLAN_ESE */
#ifdef WLAN_FEATURE_11W
case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
@@ -1076,6 +1090,27 @@ A_UINT32 e_csr_encryption_type_to_rsn_cipherset(eCsrEncryptionType encr)
}
}
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+/**
+ * wma_roam_scan_get_cckm_mode() - Get the CCKM auth mode
+ * @roam_req: Roaming request buffer
+ * @auth_mode: Auth mode to be converted
+ *
+ * Based on LFR2.0 or LFR3.0, return the proper auth type
+ *
+ * Return: if LFR2.0, then return WMI_AUTH_CCKM for backward compatibility
+ * if LFR3.0 then return the appropriate auth type
+ */
+static uint32_t wma_roam_scan_get_cckm_mode(tSirRoamOffloadScanReq *roam_req,
+ uint32_t auth_mode)
+{
+ if (roam_req->RoamOffloadEnabled)
+ return auth_mode;
+ else
+ return WMI_AUTH_CCKM;
+
+}
+#endif
/**
* wma_roam_scan_fill_ap_profile() - fill ap_profile
* @wma_handle: wma handle
@@ -1092,6 +1127,7 @@ void wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle,
tSirRoamOffloadScanReq *roam_req,
wmi_ap_profile *ap_profile_p)
{
+ uint32_t rsn_authmode;
qdf_mem_zero(ap_profile_p, sizeof(wmi_ap_profile));
if (roam_req == NULL) {
ap_profile_p->ssid.ssid_len = 0;
@@ -1108,8 +1144,16 @@ void wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle,
roam_req->ConnectedNetwork.ssId.ssId,
ap_profile_p->ssid.ssid_len);
ap_profile_p->rsn_authmode =
- e_csr_auth_type_to_rsn_authmode(roam_req->ConnectedNetwork.authentication,
- roam_req->ConnectedNetwork.encryption);
+ e_csr_auth_type_to_rsn_authmode(
+ roam_req->ConnectedNetwork.authentication,
+ roam_req->ConnectedNetwork.encryption);
+ rsn_authmode = ap_profile_p->rsn_authmode;
+
+ if ((rsn_authmode == WMI_AUTH_CCKM_WPA) ||
+ (rsn_authmode == WMI_AUTH_CCKM_RSNA))
+ ap_profile_p->rsn_authmode =
+ wma_roam_scan_get_cckm_mode(
+ roam_req, rsn_authmode);
ap_profile_p->rsn_ucastcipherset =
e_csr_encryption_type_to_rsn_cipherset(roam_req->ConnectedNetwork.encryption);
ap_profile_p->rsn_mcastcipherset =
@@ -1125,6 +1169,136 @@ void wma_roam_scan_fill_ap_profile(tp_wma_handle wma_handle,
}
/**
+ * wma_process_set_pdev_ie_req() - process the pdev set IE req
+ * @wma: Pointer to wma handle
+ * @ie_params: Pointer to IE data.
+ *
+ * Sends the WMI req to set the IE to FW.
+ *
+ * Return: None
+ */
+void wma_process_set_pdev_ie_req(tp_wma_handle wma,
+ struct set_ie_param *ie_params)
+{
+ if (ie_params->ie_type == DOT11_HT_IE)
+ wma_process_set_pdev_ht_ie_req(wma, ie_params);
+ if (ie_params->ie_type == DOT11_VHT_IE)
+ wma_process_set_pdev_vht_ie_req(wma, ie_params);
+
+ qdf_mem_free(ie_params->ie_ptr);
+}
+
+/**
+ * wma_process_set_pdev_ht_ie_req() - sends HT IE data to FW
+ * @wma: Pointer to wma handle
+ * @ie_params: Pointer to IE data.
+ * @nss: Nss values to prepare the HT IE.
+ *
+ * Sends the WMI req to set the HT IE to FW.
+ *
+ * Return: None
+ */
+void wma_process_set_pdev_ht_ie_req(tp_wma_handle wma,
+ struct set_ie_param *ie_params)
+{
+ int ret;
+ wmi_pdev_set_ht_ie_cmd_fixed_param *cmd;
+ wmi_buf_t buf;
+ uint16_t len;
+ uint16_t ie_len_pad;
+ uint8_t *buf_ptr;
+
+ len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
+ ie_len_pad = roundup(ie_params->ie_len, sizeof(uint32_t));
+ len += ie_len_pad;
+
+ buf = wmi_buf_alloc(wma->wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
+ return;
+ }
+ cmd = (wmi_pdev_set_ht_ie_cmd_fixed_param *) wmi_buf_data(buf);
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_pdev_set_ht_ie_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_pdev_set_ht_ie_cmd_fixed_param));
+ cmd->reserved0 = 0;
+ cmd->ie_len = ie_params->ie_len;
+ cmd->tx_streams = ie_params->nss;
+ cmd->rx_streams = ie_params->nss;
+ WMA_LOGD("Setting pdev HT ie with Nss = %u",
+ ie_params->nss);
+ buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad);
+ if (ie_params->ie_len) {
+ qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
+ (uint8_t *)ie_params->ie_ptr,
+ ie_params->ie_len);
+ }
+ ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+ WMI_PDEV_SET_HT_CAP_IE_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE("Failed to send set param command ret = %d", ret);
+ wmi_buf_free(buf);
+ }
+}
+
+/**
+ * wma_process_set_pdev_vht_ie_req() - sends VHT IE data to FW
+ * @wma: Pointer to wma handle
+ * @ie_params: Pointer to IE data.
+ * @nss: Nss values to prepare the VHT IE.
+ *
+ * Sends the WMI req to set the VHT IE to FW.
+ *
+ * Return: None
+ */
+void wma_process_set_pdev_vht_ie_req(tp_wma_handle wma,
+ struct set_ie_param *ie_params)
+{
+ int ret;
+ wmi_pdev_set_vht_ie_cmd_fixed_param *cmd;
+ wmi_buf_t buf;
+ uint16_t len;
+ uint16_t ie_len_pad;
+ uint8_t *buf_ptr;
+
+ len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
+ ie_len_pad = roundup(ie_params->ie_len, sizeof(uint32_t));
+ len += ie_len_pad;
+
+ buf = wmi_buf_alloc(wma->wmi_handle, len);
+ if (!buf) {
+ WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
+ return;
+ }
+ cmd = (wmi_pdev_set_vht_ie_cmd_fixed_param *) wmi_buf_data(buf);
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_pdev_set_vht_ie_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_pdev_set_vht_ie_cmd_fixed_param));
+ cmd->reserved0 = 0;
+ cmd->ie_len = ie_params->ie_len;
+ cmd->tx_streams = ie_params->nss;
+ cmd->rx_streams = ie_params->nss;
+ WMA_LOGD("Setting pdev VHT ie with Nss = %u",
+ ie_params->nss);
+ buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad);
+ if (ie_params->ie_len) {
+ qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
+ (uint8_t *)ie_params->ie_ptr,
+ ie_params->ie_len);
+ }
+ ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+ WMI_PDEV_SET_VHT_CAP_IE_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE("Failed to send set param command ret = %d", ret);
+ wmi_buf_free(buf);
+ }
+}
+
+/**
* wma_roam_scan_scan_params() - fill roam scan params
* @wma_handle: wma handle
* @pMac: Mac ptr
diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c
index d5cb5c1219d3..dc6475e1098d 100644
--- a/core/wma/src/wma_utils.c
+++ b/core/wma/src/wma_utils.c
@@ -3383,6 +3383,25 @@ uint32_t wma_get_vht_ch_width(void)
}
/**
+ * wma_get_num_of_setbits_from_bitmask() - to get num of setbits from bitmask
+ * @mask: given bitmask
+ *
+ * This helper function should return number of setbits from bitmask
+ *
+ * Return: number of setbits from bitmask
+ */
+uint32_t wma_get_num_of_setbits_from_bitmask(uint32_t mask)
+{
+ uint32_t num_of_setbits = 0;
+
+ while (mask) {
+ mask &= (mask - 1);
+ num_of_setbits++;
+ }
+ return num_of_setbits;
+}
+
+/**
* wma_config_debug_module_cmd - set debug log config
* @wmi_handle: wmi layer handle
* @param: debug log parameter