/* * This function sets up the CFG802.11 specific HT capability fields * with default values. * * The following default values are set - * - HT Supported = True * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE * - HT Capabilities supported by firmware * - MCS information, Rx mask = 0xff * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) */ static void mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, struct mwifiex_private *priv) { int rx_mcs_supp; struct ieee80211_mcs_info mcs_set; u8 *mcs = (u8 *)&mcs_set; struct mwifiex_adapter *adapter = priv->adapter; ht_info->ht_supported = true; ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); /* Fill HT capability information */ if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; else ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) ht_info->cap |= IEEE80211_HT_CAP_SGI_20; else ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20; if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) ht_info->cap |= IEEE80211_HT_CAP_SGI_40; else ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; else ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; else ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; ht_info->cap |= IEEE80211_HT_CAP_SM_PS; rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); /* Set MCS for 1x1 */ memset(mcs, 0xff, rx_mcs_supp); /* Clear all the other values */ memset(&mcs[rx_mcs_supp], 0, sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); if (priv->bss_mode == NL80211_IFTYPE_STATION || ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ SETHT_MCS32(mcs_set.rx_mask); memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info)); ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; }
/** * @brief This function prints the 802.11n device capability * * @param pmadapter A pointer to mlan_adapter structure * @param cap Capability value * * @return N/A */ void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap) { ENTER(); PRINTM(MINFO, "GET_HW_SPEC: Maximum MSDU length = %s octets\n", (ISSUPP_MAXAMSDU(cap) ? "7935" : "3839")); PRINTM(MINFO, "GET_HW_SPEC: Beam forming %s\n", (ISSUPP_BEAMFORMING(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: Greenfield preamble %s\n", (ISSUPP_GREENFIELD(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: AMPDU %s\n", (ISSUPP_AMPDU(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: MIMO Power Save %s\n", (ISSUPP_MIMOPS(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n", (ISSUPP_RXSTBC(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n", (ISSUPP_TXSTBC(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: Short GI for 40 Mhz %s\n", (ISSUPP_SHORTGI40(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: Short GI for 20 Mhz %s\n", (ISSUPP_SHORTGI20(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: LDPC coded packet receive %s\n", (ISSUPP_RXLDPC(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: Number of Delayed Block Ack streams = %d\n", GET_DELAYEDBACK(cap)); PRINTM(MINFO, "GET_HW_SPEC: Number of Immediate Block Ack streams = %d\n", GET_IMMEDIATEBACK(cap)); PRINTM(MINFO, "GET_HW_SPEC: 40 Mhz channel width %s\n", (ISSUPP_CHANWIDTH40(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: 20 Mhz channel width %s\n", (ISSUPP_CHANWIDTH20(cap) ? "supported" : "not supported")); PRINTM(MINFO, "GET_HW_SPEC: 10 Mhz channel width %s\n", (ISSUPP_CHANWIDTH10(cap) ? "supported" : "not supported")); if (ISSUPP_RXANTENNAA(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna A\n"); } if (ISSUPP_RXANTENNAB(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna B\n"); } if (ISSUPP_RXANTENNAC(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna C\n"); } if (ISSUPP_RXANTENNAD(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Rx antenna D\n"); } if (ISSUPP_TXANTENNAA(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna A\n"); } if (ISSUPP_TXANTENNAB(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna B\n"); } if (ISSUPP_TXANTENNAC(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna C\n"); } if (ISSUPP_TXANTENNAD(cap)) { PRINTM(MINFO, "GET_HW_SPEC: Presence of Tx antenna D\n"); } LEAVE(); return; }
/** * @brief This function append the 802_11N tlv * * @param pmpriv A pointer to mlan_private structure * @param pbss_desc A pointer to BSSDescriptor_t structure * @param ppbuffer A Pointer to command buffer pointer * * @return bytes added to the buffer */ int wlan_cmd_append_11n_tlv(IN mlan_private * pmpriv, IN BSSDescriptor_t * pbss_desc, OUT t_u8 ** ppbuffer) { pmlan_adapter pmadapter = pmpriv->adapter; MrvlIETypes_HTCap_t *pht_cap; MrvlIETypes_HTInfo_t *pht_info; MrvlIEtypes_ChanListParamSet_t *pchan_list; MrvlIETypes_2040BSSCo_t *p2040_bss_co; MrvlIETypes_ExtCap_t *pext_cap; int ret_len = 0; ENTER(); /* Null Checks */ if (ppbuffer == 0) { LEAVE(); return 0; } if (*ppbuffer == 0) { LEAVE(); return 0; } if (pbss_desc->pht_cap) { pht_cap = (MrvlIETypes_HTCap_t *) * ppbuffer; memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t)); pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY); pht_cap->header.len = sizeof(HTCap_t); memcpy(pmadapter, (t_u8 *) pht_cap + sizeof(MrvlIEtypesHeader_t), (t_u8 *) pbss_desc->pht_cap + sizeof(IEEEtypes_Header_t), pht_cap->header.len); pht_cap->ht_cap.ht_cap_info = wlan_le16_to_cpu(pht_cap->ht_cap.ht_cap_info); wlan_fill_cap_info(pmpriv, pht_cap); pht_cap->ht_cap.ht_cap_info = wlan_cpu_to_le16(pht_cap->ht_cap.ht_cap_info); HEXDUMP("HT_CAPABILITIES IE", (t_u8 *) pht_cap, sizeof(MrvlIETypes_HTCap_t)); *ppbuffer += sizeof(MrvlIETypes_HTCap_t); ret_len += sizeof(MrvlIETypes_HTCap_t); pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len); } if (pbss_desc->pht_info) { if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) { pht_info = (MrvlIETypes_HTInfo_t *) * ppbuffer; memset(pmadapter, pht_info, 0, sizeof(MrvlIETypes_HTInfo_t)); pht_info->header.type = wlan_cpu_to_le16(HT_OPERATION); pht_info->header.len = sizeof(HTInfo_t); memcpy(pmadapter, (t_u8 *) pht_info + sizeof(MrvlIEtypesHeader_t), (t_u8 *) pbss_desc->pht_info + sizeof(IEEEtypes_Header_t), pht_info->header.len); if (!ISSUPP_CHANWIDTH40(pmadapter->hw_dot_11n_dev_cap) || !ISSUPP_CHANWIDTH40(pmadapter->usr_dot_11n_dev_cap)) { RESET_CHANWIDTH40(pht_info->ht_info.field2); } *ppbuffer += sizeof(MrvlIETypes_HTInfo_t); ret_len += sizeof(MrvlIETypes_HTInfo_t); pht_info->header.len = wlan_cpu_to_le16(pht_info->header.len); } pchan_list = (MrvlIEtypes_ChanListParamSet_t *) * ppbuffer; memset(pmadapter, pchan_list, 0, sizeof(MrvlIEtypes_ChanListParamSet_t)); pchan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST); pchan_list->header.len = sizeof(MrvlIEtypes_ChanListParamSet_t) - sizeof(MrvlIEtypesHeader_t); pchan_list->chan_scan_param[0].chan_number = pbss_desc->pht_info->ht_info.pri_chan; pchan_list->chan_scan_param[0].radio_type = wlan_band_to_radio_type((t_u8) pbss_desc->bss_band); if ((ISSUPP_CHANWIDTH40(pmadapter->hw_dot_11n_dev_cap) && ISSUPP_CHANWIDTH40(pmadapter->usr_dot_11n_dev_cap)) && ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.field2)) SET_SECONDARYCHAN(pchan_list->chan_scan_param[0].radio_type, GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info. field2)); HEXDUMP("ChanList", (t_u8 *) pchan_list, sizeof(MrvlIEtypes_ChanListParamSet_t)); HEXDUMP("pht_info", (t_u8 *) pbss_desc->pht_info, sizeof(MrvlIETypes_HTInfo_t) - 2); *ppbuffer += sizeof(MrvlIEtypes_ChanListParamSet_t); ret_len += sizeof(MrvlIEtypes_ChanListParamSet_t); pchan_list->header.len = wlan_cpu_to_le16(pchan_list->header.len); } if (pbss_desc->pbss_co_2040) { p2040_bss_co = (MrvlIETypes_2040BSSCo_t *) * ppbuffer; memset(pmadapter, p2040_bss_co, 0, sizeof(MrvlIETypes_2040BSSCo_t)); p2040_bss_co->header.type = wlan_cpu_to_le16(BSSCO_2040); p2040_bss_co->header.len = sizeof(BSSCo2040_t); memcpy(pmadapter, (t_u8 *) p2040_bss_co + sizeof(MrvlIEtypesHeader_t), (t_u8 *) pbss_desc->pbss_co_2040 + sizeof(IEEEtypes_Header_t), p2040_bss_co->header.len); HEXDUMP("20/40 BSS Coexistence IE", (t_u8 *) p2040_bss_co, sizeof(MrvlIETypes_2040BSSCo_t)); *ppbuffer += sizeof(MrvlIETypes_2040BSSCo_t); ret_len += sizeof(MrvlIETypes_2040BSSCo_t); p2040_bss_co->header.len = wlan_cpu_to_le16(p2040_bss_co->header.len); } if (pbss_desc->pext_cap) { pext_cap = (MrvlIETypes_ExtCap_t *) * ppbuffer; memset(pmadapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t)); pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY); pext_cap->header.len = sizeof(ExtCap_t); memcpy(pmadapter, (t_u8 *) pext_cap + sizeof(MrvlIEtypesHeader_t), (t_u8 *) pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t), pext_cap->header.len); HEXDUMP("Extended Capabilities IE", (t_u8 *) pext_cap, sizeof(MrvlIETypes_ExtCap_t)); *ppbuffer += sizeof(MrvlIETypes_ExtCap_t); ret_len += sizeof(MrvlIETypes_ExtCap_t); pext_cap->header.len = wlan_cpu_to_le16(pext_cap->header.len); } LEAVE(); return ret_len; }
/** * @brief This function fills the cap info * * @param priv A pointer to mlan_private structure * @param pht_cap A pointer to MrvlIETypes_HTCap_t structure * * @return N/A */ void wlan_fill_cap_info(mlan_private * priv, MrvlIETypes_HTCap_t * pht_cap) { mlan_adapter *pmadapter = priv->adapter; int rx_mcs_supp; ENTER(); if (ISSUPP_CHANWIDTH40(pmadapter->hw_dot_11n_dev_cap) && ISSUPP_CHANWIDTH40(pmadapter->usr_dot_11n_dev_cap)) SETHT_SUPPCHANWIDTH(pht_cap->ht_cap.ht_cap_info); else RESETHT_SUPPCHANWIDTH(pht_cap->ht_cap.ht_cap_info); if (ISSUPP_GREENFIELD(pmadapter->hw_dot_11n_dev_cap) && ISSUPP_GREENFIELD(pmadapter->usr_dot_11n_dev_cap)) SETHT_GREENFIELD(pht_cap->ht_cap.ht_cap_info); else RESETHT_GREENFIELD(pht_cap->ht_cap.ht_cap_info); if (ISSUPP_SHORTGI20(pmadapter->hw_dot_11n_dev_cap) && ISSUPP_SHORTGI20(pmadapter->usr_dot_11n_dev_cap)) SETHT_SHORTGI20(pht_cap->ht_cap.ht_cap_info); else RESETHT_SHORTGI20(pht_cap->ht_cap.ht_cap_info); if (ISSUPP_SHORTGI40(pmadapter->hw_dot_11n_dev_cap) && ISSUPP_SHORTGI40(pmadapter->usr_dot_11n_dev_cap)) SETHT_SHORTGI40(pht_cap->ht_cap.ht_cap_info); else RESETHT_SHORTGI40(pht_cap->ht_cap.ht_cap_info); /* No user config for RX STBC yet */ if (ISSUPP_RXSTBC(pmadapter->hw_dot_11n_dev_cap) && ISSUPP_RXSTBC(pmadapter->usr_dot_11n_dev_cap)) SETHT_RXSTBC(pht_cap->ht_cap.ht_cap_info, 1); else RESETHT_RXSTBC(pht_cap->ht_cap.ht_cap_info); /* No user config for TX STBC yet */ if (ISSUPP_TXSTBC(pmadapter->hw_dot_11n_dev_cap)) SETHT_TXSTBC(pht_cap->ht_cap.ht_cap_info); else RESETHT_TXSTBC(pht_cap->ht_cap.ht_cap_info); /* No user config for Delayed BACK yet */ if (GET_DELAYEDBACK(pmadapter->hw_dot_11n_dev_cap)) SETHT_DELAYEDBACK(pht_cap->ht_cap.ht_cap_info); else RESETHT_DELAYEDBACK(pht_cap->ht_cap.ht_cap_info); if (ISENABLED_40MHZ_INTOLARENT(pmadapter->usr_dot_11n_dev_cap)) SETHT_40MHZ_INTOLARANT(pht_cap->ht_cap.ht_cap_info); else RESETHT_40MHZ_INTOLARANT(pht_cap->ht_cap.ht_cap_info); SETAMPDU_SIZE(pht_cap->ht_cap.ampdu_param, AMPDU_FACTOR_64K); SETAMPDU_SPACING(pht_cap->ht_cap.ampdu_param, 0); /* Need change to support 8k AMSDU receive */ RESETHT_MAXAMSDU(pht_cap->ht_cap.ht_cap_info); rx_mcs_supp = GET_RXMCSSUPP(pmadapter->hw_dev_mcs_support); /** Maximum MCS */ #define NUM_MCS_FIELD 16 /* Set MCS for 1x1 */ memset(pmadapter, (t_u8 *) pht_cap->ht_cap.supported_mcs_set, 0xff, rx_mcs_supp); /* Clear all the other values */ memset(pmadapter, (t_u8 *) & pht_cap->ht_cap.supported_mcs_set[rx_mcs_supp], 0, NUM_MCS_FIELD - rx_mcs_supp); if (priv->bss_mode == MLAN_BSS_MODE_INFRA || (ISSUPP_CHANWIDTH40(pmadapter->hw_dot_11n_dev_cap) && ISSUPP_CHANWIDTH40(pmadapter->usr_dot_11n_dev_cap))) /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ SETHT_MCS32(pht_cap->ht_cap.supported_mcs_set); /* Clear RD responder bit */ RESETHT_EXTCAP_RDG(pht_cap->ht_cap.ht_ext_cap); LEAVE(); }