|
@@ -6580,19 +6580,80 @@ void lim_add_self_he_cap(tpAddStaParams add_sta_params, struct pe_session *sessi
|
|
|
sizeof(add_sta_params->he_op));
|
|
|
}
|
|
|
|
|
|
+static bool lim_check_is_bss_greater_than_4_nss_supp(struct pe_session *session,
|
|
|
+ tDot11fIEhe_cap *he_cap)
|
|
|
+{
|
|
|
+ uint8_t i;
|
|
|
+ uint16_t mcs_map;
|
|
|
+#define NSS_4 4
|
|
|
+#define NSS_8 8
|
|
|
+
|
|
|
+ if (!session->he_capable || !he_cap->present)
|
|
|
+ return false;
|
|
|
+ mcs_map = he_cap->rx_he_mcs_map_lt_80;
|
|
|
+ for (i = NSS_4; i < NSS_8; i++) {
|
|
|
+ if (((mcs_map >> (i * 2)) & 0x3) != 0x3)
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+bool lim_check_he_80_mcs11_supp(struct pe_session *session,
|
|
|
+ tDot11fIEhe_cap *he_cap)
|
|
|
+{
|
|
|
+ uint16_t rx_mcs_map;
|
|
|
+ uint16_t tx_mcs_map;
|
|
|
+
|
|
|
+ rx_mcs_map = he_cap->rx_he_mcs_map_lt_80;
|
|
|
+ tx_mcs_map = he_cap->tx_he_mcs_map_lt_80;
|
|
|
+ if ((session->nss == NSS_1x1_MODE) &&
|
|
|
+ ((HE_GET_MCS_4_NSS(rx_mcs_map, 1) == HE_MCS_0_11) ||
|
|
|
+ (HE_GET_MCS_4_NSS(tx_mcs_map, 1) == HE_MCS_0_11)))
|
|
|
+ return true;
|
|
|
+
|
|
|
+ if ((session->nss == NSS_2x2_MODE) &&
|
|
|
+ ((HE_GET_MCS_4_NSS(rx_mcs_map, 2) == HE_MCS_0_11) ||
|
|
|
+ (HE_GET_MCS_4_NSS(tx_mcs_map, 2) == HE_MCS_0_11)))
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * lim_check_he_ldpc_cap() - set he ldpc coding to one if
|
|
|
+ * channel width is > 20 or mcs 10/11 bit are supported or
|
|
|
+ * nss is greater than 4.
|
|
|
+ * @beacon_struct: beacon structure
|
|
|
+ * @session: A pointer to session entry.
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+
|
|
|
+static void lim_check_and_force_he_ldpc_cap(struct pe_session *session,
|
|
|
+ tDot11fIEhe_cap *he_cap)
|
|
|
+{
|
|
|
+ if (!he_cap->ldpc_coding &&
|
|
|
+ (session->ch_width > CH_WIDTH_20MHZ ||
|
|
|
+ lim_check_he_80_mcs11_supp(session, he_cap) ||
|
|
|
+ lim_check_is_bss_greater_than_4_nss_supp(session, he_cap)))
|
|
|
+ he_cap->ldpc_coding = 1;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* lim_intersect_he_caps() - Intersect peer capability and self capability
|
|
|
* @rcvd_he: pointer to received peer capability
|
|
|
- * @session_he: pointer to self capability
|
|
|
* @peer_he: pointer to Intersected capability
|
|
|
+ * @session: A pointer to session entry.
|
|
|
*
|
|
|
* Return: None
|
|
|
*/
|
|
|
static void lim_intersect_he_caps(tDot11fIEhe_cap *rcvd_he,
|
|
|
- tDot11fIEhe_cap *session_he,
|
|
|
- tDot11fIEhe_cap *peer_he)
|
|
|
+ tDot11fIEhe_cap *peer_he,
|
|
|
+ struct pe_session *session)
|
|
|
{
|
|
|
uint8_t val;
|
|
|
+ tDot11fIEhe_cap *session_he = &session->he_config;
|
|
|
|
|
|
qdf_mem_copy(peer_he, rcvd_he, sizeof(*peer_he));
|
|
|
|
|
@@ -6600,6 +6661,7 @@ static void lim_intersect_he_caps(tDot11fIEhe_cap *rcvd_he,
|
|
|
peer_he->fragmentation);
|
|
|
|
|
|
peer_he->ldpc_coding &= session_he->ldpc_coding;
|
|
|
+ lim_check_and_force_he_ldpc_cap(session, peer_he);
|
|
|
|
|
|
if (session_he->tb_ppdu_tx_stbc_lt_80mhz && peer_he->rx_stbc_lt_80mhz)
|
|
|
peer_he->rx_stbc_lt_80mhz = 1;
|
|
@@ -6651,7 +6713,6 @@ void lim_intersect_sta_he_caps(struct mac_context *mac_ctx,
|
|
|
tpDphHashNode sta_ds)
|
|
|
{
|
|
|
tDot11fIEhe_cap *rcvd_he = &assoc_req->he_cap;
|
|
|
- tDot11fIEhe_cap *session_he = &session->he_config;
|
|
|
tDot11fIEhe_cap *peer_he = &sta_ds->he_config;
|
|
|
|
|
|
if (!sta_ds->mlmStaContext.he_capable)
|
|
@@ -6661,7 +6722,7 @@ void lim_intersect_sta_he_caps(struct mac_context *mac_ctx,
|
|
|
if (!IS_DOT11_MODE_HE(session->dot11mode))
|
|
|
return;
|
|
|
|
|
|
- lim_intersect_he_caps(rcvd_he, session_he, peer_he);
|
|
|
+ lim_intersect_he_caps(rcvd_he, peer_he, session);
|
|
|
|
|
|
/* If MCS 12/13 is supported from assoc QCN IE */
|
|
|
if (assoc_req->qcn_ie.present &&
|
|
@@ -6686,7 +6747,6 @@ void lim_intersect_ap_he_caps(struct pe_session *session, struct bss_params *add
|
|
|
tSchBeaconStruct *beacon, tpSirAssocRsp assoc_rsp)
|
|
|
{
|
|
|
tDot11fIEhe_cap *rcvd_he;
|
|
|
- tDot11fIEhe_cap *session_he = &session->he_config;
|
|
|
tDot11fIEhe_cap *peer_he = &add_bss->staContext.he_config;
|
|
|
|
|
|
if (assoc_rsp && assoc_rsp->he_cap.present)
|
|
@@ -6694,7 +6754,7 @@ void lim_intersect_ap_he_caps(struct pe_session *session, struct bss_params *add
|
|
|
else
|
|
|
rcvd_he = &beacon->he_cap;
|
|
|
|
|
|
- lim_intersect_he_caps(rcvd_he, session_he, peer_he);
|
|
|
+ lim_intersect_he_caps(rcvd_he, peer_he, session);
|
|
|
add_bss->staContext.he_capable = true;
|
|
|
}
|
|
|
|
|
@@ -6741,98 +6801,35 @@ void lim_update_he_6gop_assoc_resp(struct bss_params *pAddBssParams,
|
|
|
pAddBssParams->staContext.ch_width = pAddBssParams->ch_width;
|
|
|
}
|
|
|
|
|
|
-static bool lim_check_is_bss_greater_than_4_nss_supp(struct pe_session *session,
|
|
|
- tDot11fIEhe_cap *he_cap)
|
|
|
-{
|
|
|
- uint8_t i;
|
|
|
- uint16_t mcs_map;
|
|
|
-#define NSS_4 4
|
|
|
-#define NSS_8 8
|
|
|
-
|
|
|
- if (!session->he_capable || !he_cap->present)
|
|
|
- return false;
|
|
|
- mcs_map = he_cap->rx_he_mcs_map_lt_80;
|
|
|
- for (i = NSS_4; i < NSS_8; i++) {
|
|
|
- if (((mcs_map >> (i * 2)) & 0x3) != 0x3)
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-bool lim_check_he_80_mcs11_supp(struct pe_session *session,
|
|
|
- tDot11fIEhe_cap *he_cap)
|
|
|
-{
|
|
|
- uint16_t rx_mcs_map;
|
|
|
- uint16_t tx_mcs_map;
|
|
|
-
|
|
|
- rx_mcs_map = he_cap->rx_he_mcs_map_lt_80;
|
|
|
- tx_mcs_map = he_cap->tx_he_mcs_map_lt_80;
|
|
|
- if ((session->nss == NSS_1x1_MODE) &&
|
|
|
- ((HE_GET_MCS_4_NSS(rx_mcs_map, 1) == HE_MCS_0_11) ||
|
|
|
- (HE_GET_MCS_4_NSS(tx_mcs_map, 1) == HE_MCS_0_11)))
|
|
|
- return true;
|
|
|
-
|
|
|
- if ((session->nss == NSS_2x2_MODE) &&
|
|
|
- ((HE_GET_MCS_4_NSS(rx_mcs_map, 2) == HE_MCS_0_11) ||
|
|
|
- (HE_GET_MCS_4_NSS(tx_mcs_map, 2) == HE_MCS_0_11)))
|
|
|
- return true;
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * lim_check_he_ldpc_cap() - set he ladpc coding to one if
|
|
|
- * channel width is > 20 or mcs 10/11 bit are supported or
|
|
|
- * nss is greater than 4.
|
|
|
- * @beacon_struct: beacon structure
|
|
|
- * @session: A pointer to session entry.
|
|
|
- *
|
|
|
- * Return: None
|
|
|
- */
|
|
|
-
|
|
|
-static void lim_check_and_force_he_ldpc_cap(struct pe_session *session,
|
|
|
- tDot11fIEhe_cap *he_cap)
|
|
|
-{
|
|
|
- if (!he_cap->ldpc_coding &&
|
|
|
- !WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq) &&
|
|
|
- (session->ch_width > CH_WIDTH_20MHZ ||
|
|
|
- lim_check_he_80_mcs11_supp(session, he_cap) ||
|
|
|
- lim_check_is_bss_greater_than_4_nss_supp(session, he_cap)))
|
|
|
- he_cap->ldpc_coding = 1;
|
|
|
-}
|
|
|
-
|
|
|
void lim_update_stads_he_caps(struct mac_context *mac_ctx,
|
|
|
tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
|
|
|
struct pe_session *session_entry,
|
|
|
tSchBeaconStruct *beacon)
|
|
|
{
|
|
|
- tDot11fIEhe_cap *he_cap;
|
|
|
-
|
|
|
- he_cap = &assoc_rsp->he_cap;
|
|
|
-
|
|
|
- if (assoc_rsp->he_cap.present) {
|
|
|
- he_cap = &assoc_rsp->he_cap;
|
|
|
- } else if (beacon && beacon->he_cap.present) {
|
|
|
+ if (!assoc_rsp->he_cap.present && beacon && beacon->he_cap.present) {
|
|
|
/* Use beacon HE caps if assoc resp doesn't have he caps */
|
|
|
pe_debug("he_caps missing in assoc rsp");
|
|
|
- he_cap = &beacon->he_cap;
|
|
|
qdf_mem_copy(&assoc_rsp->he_cap, &beacon->he_cap,
|
|
|
- sizeof(*he_cap));
|
|
|
- } else {
|
|
|
- return;
|
|
|
+ sizeof(tDot11fIEhe_cap));
|
|
|
}
|
|
|
|
|
|
- sta_ds->mlmStaContext.he_capable = he_cap->present;
|
|
|
+ /* assoc resp and beacon doesn't have he caps */
|
|
|
+ if (!assoc_rsp->he_cap.present)
|
|
|
+ return;
|
|
|
+
|
|
|
+ sta_ds->mlmStaContext.he_capable = assoc_rsp->he_cap.present;
|
|
|
|
|
|
- /* setting lpdc_coding if any of assoc_rsp or beacon has ladpc_coding
|
|
|
+ /* setting ldpc_coding if any of assoc_rsp or beacon has ldpc_coding
|
|
|
* enabled
|
|
|
*/
|
|
|
if (beacon)
|
|
|
- he_cap->ldpc_coding |= beacon->he_cap.ldpc_coding;
|
|
|
- lim_check_and_force_he_ldpc_cap(session_entry, he_cap);
|
|
|
+ assoc_rsp->he_cap.ldpc_coding |= beacon->he_cap.ldpc_coding;
|
|
|
+ lim_check_and_force_he_ldpc_cap(session_entry, &assoc_rsp->he_cap);
|
|
|
+ if (beacon)
|
|
|
+ beacon->he_cap.ldpc_coding = assoc_rsp->he_cap.ldpc_coding;
|
|
|
|
|
|
- qdf_mem_copy(&sta_ds->he_config, he_cap, sizeof(*he_cap));
|
|
|
+ qdf_mem_copy(&sta_ds->he_config, &assoc_rsp->he_cap,
|
|
|
+ sizeof(tDot11fIEhe_cap));
|
|
|
|
|
|
/* If HE is not supported, do not fill sta_ds and return */
|
|
|
if (!IS_DOT11_MODE_HE(session_entry->dot11mode))
|