Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * NXP Wireless LAN device driver: 802.11ac
0004  *
0005  * Copyright 2011-2020 NXP
0006  */
0007 
0008 #include "decl.h"
0009 #include "ioctl.h"
0010 #include "fw.h"
0011 #include "main.h"
0012 #include "11ac.h"
0013 
0014 /* Tables of the MCS map to the highest data rate (in Mbps) supported
0015  * for long GI.
0016  */
0017 static const u16 max_rate_lgi_80MHZ[8][3] = {
0018     {0x124, 0x15F, 0x186},  /* NSS = 1 */
0019     {0x249, 0x2BE, 0x30C},  /* NSS = 2 */
0020     {0x36D, 0x41D, 0x492},  /* NSS = 3 */
0021     {0x492, 0x57C, 0x618},  /* NSS = 4 */
0022     {0x5B6, 0x6DB, 0x79E},  /* NSS = 5 */
0023     {0x6DB, 0x83A, 0x0},    /* NSS = 6 */
0024     {0x7FF, 0x999, 0xAAA},  /* NSS = 7 */
0025     {0x924, 0xAF8, 0xC30}   /* NSS = 8 */
0026 };
0027 
0028 static const u16 max_rate_lgi_160MHZ[8][3] = {
0029     {0x249, 0x2BE, 0x30C},   /* NSS = 1 */
0030     {0x492, 0x57C, 0x618},   /* NSS = 2 */
0031     {0x6DB, 0x83A, 0x0},     /* NSS = 3 */
0032     {0x924, 0xAF8, 0xC30},   /* NSS = 4 */
0033     {0xB6D, 0xDB6, 0xF3C},   /* NSS = 5 */
0034     {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
0035     {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
0036     {0x1248, 0x15F0, 0x1860} /* NSS = 8 */
0037 };
0038 
0039 /* This function converts the 2-bit MCS map to the highest long GI
0040  * VHT data rate.
0041  */
0042 static u16
0043 mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
0044                   u8 bands, u16 mcs_map)
0045 {
0046     u8 i, nss, mcs;
0047     u16 max_rate = 0;
0048     u32 usr_vht_cap_info = 0;
0049     struct mwifiex_adapter *adapter = priv->adapter;
0050 
0051     if (bands & BAND_AAC)
0052         usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
0053     else
0054         usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
0055 
0056     /* find the max NSS supported */
0057     nss = 1;
0058     for (i = 1; i <= 8; i++) {
0059         mcs = GET_VHTNSSMCS(mcs_map, i);
0060         if (mcs < IEEE80211_VHT_MCS_NOT_SUPPORTED)
0061             nss = i;
0062     }
0063     mcs = GET_VHTNSSMCS(mcs_map, nss);
0064 
0065     /* if mcs is 3, nss must be 1 (NSS = 1). Default mcs to MCS 0~9 */
0066     if (mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
0067         mcs = IEEE80211_VHT_MCS_SUPPORT_0_9;
0068 
0069     if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
0070         /* support 160 MHz */
0071         max_rate = max_rate_lgi_160MHZ[nss - 1][mcs];
0072         if (!max_rate)
0073             /* MCS9 is not supported in NSS6 */
0074             max_rate = max_rate_lgi_160MHZ[nss - 1][mcs - 1];
0075     } else {
0076         max_rate = max_rate_lgi_80MHZ[nss - 1][mcs];
0077         if (!max_rate)
0078             /* MCS9 is not supported in NSS3 */
0079             max_rate = max_rate_lgi_80MHZ[nss - 1][mcs - 1];
0080     }
0081 
0082     return max_rate;
0083 }
0084 
0085 static void
0086 mwifiex_fill_vht_cap_info(struct mwifiex_private *priv,
0087               struct ieee80211_vht_cap *vht_cap, u8 bands)
0088 {
0089     struct mwifiex_adapter *adapter = priv->adapter;
0090 
0091     if (bands & BAND_A)
0092         vht_cap->vht_cap_info =
0093                 cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a);
0094     else
0095         vht_cap->vht_cap_info =
0096                 cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg);
0097 }
0098 
0099 void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
0100                   struct ieee80211_vht_cap *vht_cap, u8 bands)
0101 {
0102     struct mwifiex_adapter *adapter = priv->adapter;
0103     u16 mcs_map_user, mcs_map_resp, mcs_map_result;
0104     u16 mcs_user, mcs_resp, nss, tmp;
0105 
0106     /* Fill VHT cap info */
0107     mwifiex_fill_vht_cap_info(priv, vht_cap, bands);
0108 
0109     /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */
0110     mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
0111     mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
0112     mcs_map_result = 0;
0113 
0114     for (nss = 1; nss <= 8; nss++) {
0115         mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
0116         mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
0117 
0118         if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
0119             (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
0120             SET_VHTNSSMCS(mcs_map_result, nss,
0121                       IEEE80211_VHT_MCS_NOT_SUPPORTED);
0122         else
0123             SET_VHTNSSMCS(mcs_map_result, nss,
0124                       min(mcs_user, mcs_resp));
0125     }
0126 
0127     vht_cap->supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result);
0128 
0129     tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
0130     vht_cap->supp_mcs.rx_highest = cpu_to_le16(tmp);
0131 
0132     /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */
0133     mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support);
0134     mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map);
0135     mcs_map_result = 0;
0136 
0137     for (nss = 1; nss <= 8; nss++) {
0138         mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
0139         mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
0140         if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
0141             (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
0142             SET_VHTNSSMCS(mcs_map_result, nss,
0143                       IEEE80211_VHT_MCS_NOT_SUPPORTED);
0144         else
0145             SET_VHTNSSMCS(mcs_map_result, nss,
0146                       min(mcs_user, mcs_resp));
0147     }
0148 
0149     vht_cap->supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result);
0150 
0151     tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
0152     vht_cap->supp_mcs.tx_highest = cpu_to_le16(tmp);
0153 
0154     return;
0155 }
0156 
0157 int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
0158                  struct mwifiex_bssdescriptor *bss_desc,
0159                  u8 **buffer)
0160 {
0161     struct mwifiex_ie_types_vhtcap *vht_cap;
0162     struct mwifiex_ie_types_oper_mode_ntf *oper_ntf;
0163     struct ieee_types_oper_mode_ntf *ieee_oper_ntf;
0164     struct mwifiex_ie_types_vht_oper *vht_op;
0165     struct mwifiex_adapter *adapter = priv->adapter;
0166     u8 supp_chwd_set;
0167     u32 usr_vht_cap_info;
0168     int ret_len = 0;
0169 
0170     if (bss_desc->bss_band & BAND_A)
0171         usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
0172     else
0173         usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
0174 
0175     /* VHT Capabilities IE */
0176     if (bss_desc->bcn_vht_cap) {
0177         vht_cap = (struct mwifiex_ie_types_vhtcap *)*buffer;
0178         memset(vht_cap, 0, sizeof(*vht_cap));
0179         vht_cap->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
0180         vht_cap->header.len  =
0181                 cpu_to_le16(sizeof(struct ieee80211_vht_cap));
0182         memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header),
0183                (u8 *)bss_desc->bcn_vht_cap,
0184                le16_to_cpu(vht_cap->header.len));
0185 
0186         mwifiex_fill_vht_cap_tlv(priv, &vht_cap->vht_cap,
0187                      bss_desc->bss_band);
0188         *buffer += sizeof(*vht_cap);
0189         ret_len += sizeof(*vht_cap);
0190     }
0191 
0192     /* VHT Operation IE */
0193     if (bss_desc->bcn_vht_oper) {
0194         if (priv->bss_mode == NL80211_IFTYPE_STATION) {
0195             vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
0196             memset(vht_op, 0, sizeof(*vht_op));
0197             vht_op->header.type =
0198                     cpu_to_le16(WLAN_EID_VHT_OPERATION);
0199             vht_op->header.len  = cpu_to_le16(sizeof(*vht_op) -
0200                       sizeof(struct mwifiex_ie_types_header));
0201             memcpy((u8 *)vht_op +
0202                 sizeof(struct mwifiex_ie_types_header),
0203                    (u8 *)bss_desc->bcn_vht_oper,
0204                    le16_to_cpu(vht_op->header.len));
0205 
0206             /* negotiate the channel width and central freq
0207              * and keep the central freq as the peer suggests
0208              */
0209             supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
0210 
0211             switch (supp_chwd_set) {
0212             case 0:
0213                 vht_op->chan_width =
0214                      min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ,
0215                        bss_desc->bcn_vht_oper->chan_width);
0216                 break;
0217             case 1:
0218                 vht_op->chan_width =
0219                      min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ,
0220                        bss_desc->bcn_vht_oper->chan_width);
0221                 break;
0222             case 2:
0223                 vht_op->chan_width =
0224                      min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ,
0225                        bss_desc->bcn_vht_oper->chan_width);
0226                 break;
0227             default:
0228                 vht_op->chan_width =
0229                      IEEE80211_VHT_CHANWIDTH_USE_HT;
0230                 break;
0231             }
0232 
0233             *buffer += sizeof(*vht_op);
0234             ret_len += sizeof(*vht_op);
0235         }
0236     }
0237 
0238     /* Operating Mode Notification IE */
0239     if (bss_desc->oper_mode) {
0240         ieee_oper_ntf = bss_desc->oper_mode;
0241         oper_ntf = (void *)*buffer;
0242         memset(oper_ntf, 0, sizeof(*oper_ntf));
0243         oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF);
0244         oper_ntf->header.len = cpu_to_le16(sizeof(u8));
0245         oper_ntf->oper_mode = ieee_oper_ntf->oper_mode;
0246         *buffer += sizeof(*oper_ntf);
0247         ret_len += sizeof(*oper_ntf);
0248     }
0249 
0250     return ret_len;
0251 }
0252 
0253 int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
0254              struct host_cmd_ds_command *cmd, u16 cmd_action,
0255              struct mwifiex_11ac_vht_cfg *cfg)
0256 {
0257     struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg;
0258 
0259     cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG);
0260     cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) +
0261                 S_DS_GEN);
0262     vhtcfg->action = cpu_to_le16(cmd_action);
0263     vhtcfg->band_config = cfg->band_config;
0264     vhtcfg->misc_config = cfg->misc_config;
0265     vhtcfg->cap_info = cpu_to_le32(cfg->cap_info);
0266     vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set);
0267     vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set);
0268 
0269     return 0;
0270 }
0271 
0272 /* This function initializes the BlockACK setup information for given
0273  * mwifiex_private structure for 11ac enabled networks.
0274  */
0275 void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv)
0276 {
0277     priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
0278 
0279     if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
0280         priv->add_ba_param.tx_win_size =
0281                        MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE;
0282         priv->add_ba_param.rx_win_size =
0283                        MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE;
0284     } else {
0285         priv->add_ba_param.tx_win_size =
0286                        MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
0287         priv->add_ba_param.rx_win_size =
0288                        MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
0289     }
0290 
0291     return;
0292 }
0293 
0294 bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv)
0295 {
0296     struct mwifiex_bssdescriptor *bss_desc;
0297     struct ieee80211_vht_operation *vht_oper;
0298 
0299     bss_desc = &priv->curr_bss_params.bss_descriptor;
0300     vht_oper = bss_desc->bcn_vht_oper;
0301 
0302     if (!bss_desc->bcn_vht_cap || !vht_oper)
0303         return false;
0304 
0305     if (vht_oper->chan_width == IEEE80211_VHT_CHANWIDTH_USE_HT)
0306         return false;
0307 
0308     return true;
0309 }
0310 
0311 u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
0312                  u32 pri_chan, u8 chan_bw)
0313 {
0314     u8 center_freq_idx = 0;
0315 
0316     if (band & BAND_AAC) {
0317         switch (pri_chan) {
0318         case 36:
0319         case 40:
0320         case 44:
0321         case 48:
0322             if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
0323                 center_freq_idx = 42;
0324             break;
0325         case 52:
0326         case 56:
0327         case 60:
0328         case 64:
0329             if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
0330                 center_freq_idx = 58;
0331             else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
0332                 center_freq_idx = 50;
0333             break;
0334         case 100:
0335         case 104:
0336         case 108:
0337         case 112:
0338             if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
0339                 center_freq_idx = 106;
0340             break;
0341         case 116:
0342         case 120:
0343         case 124:
0344         case 128:
0345             if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
0346                 center_freq_idx = 122;
0347             else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ)
0348                 center_freq_idx = 114;
0349             break;
0350         case 132:
0351         case 136:
0352         case 140:
0353         case 144:
0354             if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
0355                 center_freq_idx = 138;
0356             break;
0357         case 149:
0358         case 153:
0359         case 157:
0360         case 161:
0361             if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ)
0362                 center_freq_idx = 155;
0363             break;
0364         default:
0365             center_freq_idx = 42;
0366         }
0367     }
0368 
0369     return center_freq_idx;
0370 }