Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * NXP Wireless LAN device driver: Channel, Frequence and Power
0004  *
0005  * Copyright 2011-2020 NXP
0006  */
0007 
0008 #include "decl.h"
0009 #include "ioctl.h"
0010 #include "util.h"
0011 #include "fw.h"
0012 #include "main.h"
0013 #include "cfg80211.h"
0014 
0015 /* 100mW */
0016 #define MWIFIEX_TX_PWR_DEFAULT     20
0017 /* 100mW */
0018 #define MWIFIEX_TX_PWR_US_DEFAULT      20
0019 /* 50mW */
0020 #define MWIFIEX_TX_PWR_JP_DEFAULT      16
0021 /* 100mW */
0022 #define MWIFIEX_TX_PWR_FR_100MW        20
0023 /* 10mW */
0024 #define MWIFIEX_TX_PWR_FR_10MW         10
0025 /* 100mW */
0026 #define MWIFIEX_TX_PWR_EMEA_DEFAULT    20
0027 
0028 static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };
0029 
0030 static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
0031                            0xb0, 0x48, 0x60, 0x6c, 0 };
0032 
0033 static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96,
0034                          0x0c, 0x12, 0x18, 0x24,
0035                          0x30, 0x48, 0x60, 0x6c, 0 };
0036 
0037 static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,
0038                            0xb0, 0x48, 0x60, 0x6c, 0 };
0039 static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
0040                     0xb0, 0x48, 0x60, 0x6c, 0 };
0041 static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,
0042                     0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18,
0043                     0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,
0044                     0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68,
0045                     0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51,
0046                     0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 };
0047 
0048 static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };
0049 
0050 static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,
0051                     0x30, 0x48, 0x60, 0x6c, 0 };
0052 
0053 static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
0054                     0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
0055                     0x60, 0x6c, 0 };
0056 
0057 u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x00, 0x10, 0x20, 0x30,
0058                         0x31, 0x32, 0x40, 0x41, 0x50 };
0059 
0060 static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
0061 
0062 /* For every mcs_rate line, the first 8 bytes are for stream 1x1,
0063  * and all 16 bytes are for stream 2x2.
0064  */
0065 static const u16 mcs_rate[4][16] = {
0066     /* LGI 40M */
0067     { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
0068       0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
0069 
0070     /* SGI 40M */
0071     { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
0072       0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
0073 
0074     /* LGI 20M */
0075     { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
0076       0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
0077 
0078     /* SGI 20M */
0079     { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
0080       0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
0081 };
0082 
0083 /* AC rates */
0084 static const u16 ac_mcs_rate_nss1[8][10] = {
0085     /* LG 160M */
0086     { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
0087       0x492, 0x57C, 0x618 },
0088 
0089     /* SG 160M */
0090     { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
0091       0x514, 0x618, 0x6C6 },
0092 
0093     /* LG 80M */
0094     { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,
0095       0x249, 0x2BE, 0x30C },
0096 
0097     /* SG 80M */
0098     { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,
0099       0x28A, 0x30C, 0x363 },
0100 
0101     /* LG 40M */
0102     { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
0103       0x10E, 0x144, 0x168 },
0104 
0105     /* SG 40M */
0106     { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,
0107       0x12C, 0x168, 0x190 },
0108 
0109     /* LG 20M */
0110     { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },
0111 
0112     /* SG 20M */
0113     { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },
0114 };
0115 
0116 /* NSS2 note: the value in the table is 2 multiplier of the actual rate */
0117 static const u16 ac_mcs_rate_nss2[8][10] = {
0118     /* LG 160M */
0119     { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,
0120       0x924, 0xAF8, 0xC30 },
0121 
0122     /* SG 160M */
0123     { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,
0124       0xA28, 0xC30, 0xD8B },
0125 
0126     /* LG 80M */
0127     { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
0128       0x492, 0x57C, 0x618 },
0129 
0130     /* SG 80M */
0131     { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
0132       0x514, 0x618, 0x6C6 },
0133 
0134     /* LG 40M */
0135     { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,
0136       0x21C, 0x288, 0x2D0 },
0137 
0138     /* SG 40M */
0139     { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,
0140       0x258, 0x2D0, 0x320 },
0141 
0142     /* LG 20M */
0143     { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,
0144       0x138, 0x00 },
0145 
0146     /* SG 20M */
0147     { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121,
0148       0x15B, 0x00 },
0149 };
0150 
0151 struct region_code_mapping {
0152     u8 code;
0153     u8 region[IEEE80211_COUNTRY_STRING_LEN];
0154 };
0155 
0156 static struct region_code_mapping region_code_mapping_t[] = {
0157     { 0x10, "US " }, /* US FCC */
0158     { 0x20, "CA " }, /* IC Canada */
0159     { 0x30, "FR " }, /* France */
0160     { 0x31, "ES " }, /* Spain */
0161     { 0x32, "FR " }, /* France */
0162     { 0x40, "JP " }, /* Japan */
0163     { 0x41, "JP " }, /* Japan */
0164     { 0x50, "CN " }, /* China */
0165 };
0166 
0167 /* This function converts integer code to region string */
0168 u8 *mwifiex_11d_code_2_region(u8 code)
0169 {
0170     u8 i;
0171 
0172     /* Look for code in mapping table */
0173     for (i = 0; i < ARRAY_SIZE(region_code_mapping_t); i++)
0174         if (region_code_mapping_t[i].code == code)
0175             return region_code_mapping_t[i].region;
0176 
0177     return NULL;
0178 }
0179 
0180 /*
0181  * This function maps an index in supported rates table into
0182  * the corresponding data rate.
0183  */
0184 u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
0185                    u8 index, u8 ht_info)
0186 {
0187     u32 rate = 0;
0188     u8 mcs_index = 0;
0189     u8 bw = 0;
0190     u8 gi = 0;
0191 
0192     if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) {
0193         mcs_index = min(index & 0xF, 9);
0194 
0195         /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
0196         bw = (ht_info & 0xC) >> 2;
0197 
0198         /* LGI: gi =0, SGI: gi = 1 */
0199         gi = (ht_info & 0x10) >> 4;
0200 
0201         if ((index >> 4) == 1)  /* NSS = 2 */
0202             rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
0203         else            /* NSS = 1 */
0204             rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
0205     } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) {
0206         /* 20M: bw=0, 40M: bw=1 */
0207         bw = (ht_info & 0xC) >> 2;
0208 
0209         /* LGI: gi =0, SGI: gi = 1 */
0210         gi = (ht_info & 0x10) >> 4;
0211 
0212         if (index == MWIFIEX_RATE_BITMAP_MCS0) {
0213             if (gi == 1)
0214                 rate = 0x0D;    /* MCS 32 SGI rate */
0215             else
0216                 rate = 0x0C;    /* MCS 32 LGI rate */
0217         } else if (index < 16) {
0218             if ((bw == 1) || (bw == 0))
0219                 rate = mcs_rate[2 * (1 - bw) + gi][index];
0220             else
0221                 rate = mwifiex_data_rates[0];
0222         } else {
0223             rate = mwifiex_data_rates[0];
0224         }
0225     } else {
0226         /* 11n non-HT rates */
0227         if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
0228             index = 0;
0229         rate = mwifiex_data_rates[index];
0230     }
0231 
0232     return rate;
0233 }
0234 
0235 /* This function maps an index in supported rates table into
0236  * the corresponding data rate.
0237  */
0238 u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
0239                    u8 index, u8 ht_info)
0240 {
0241     u32 mcs_num_supp =
0242         (priv->adapter->user_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;
0243     u32 rate;
0244 
0245     if (priv->adapter->is_hw_11ac_capable)
0246         return mwifiex_index_to_acs_data_rate(priv, index, ht_info);
0247 
0248     if (ht_info & BIT(0)) {
0249         if (index == MWIFIEX_RATE_BITMAP_MCS0) {
0250             if (ht_info & BIT(2))
0251                 rate = 0x0D;    /* MCS 32 SGI rate */
0252             else
0253                 rate = 0x0C;    /* MCS 32 LGI rate */
0254         } else if (index < mcs_num_supp) {
0255             if (ht_info & BIT(1)) {
0256                 if (ht_info & BIT(2))
0257                     /* SGI, 40M */
0258                     rate = mcs_rate[1][index];
0259                 else
0260                     /* LGI, 40M */
0261                     rate = mcs_rate[0][index];
0262             } else {
0263                 if (ht_info & BIT(2))
0264                     /* SGI, 20M */
0265                     rate = mcs_rate[3][index];
0266                 else
0267                     /* LGI, 20M */
0268                     rate = mcs_rate[2][index];
0269             }
0270         } else
0271             rate = mwifiex_data_rates[0];
0272     } else {
0273         if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
0274             index = 0;
0275         rate = mwifiex_data_rates[index];
0276     }
0277     return rate;
0278 }
0279 
0280 /*
0281  * This function returns the current active data rates.
0282  *
0283  * The result may vary depending upon connection status.
0284  */
0285 u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates)
0286 {
0287     if (!priv->media_connected)
0288         return mwifiex_get_supported_rates(priv, rates);
0289     else
0290         return mwifiex_copy_rates(rates, 0,
0291                       priv->curr_bss_params.data_rates,
0292                       priv->curr_bss_params.num_of_rates);
0293 }
0294 
0295 /*
0296  * This function locates the Channel-Frequency-Power triplet based upon
0297  * band and channel/frequency parameters.
0298  */
0299 struct mwifiex_chan_freq_power *
0300 mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)
0301 {
0302     struct mwifiex_chan_freq_power *cfp = NULL;
0303     struct ieee80211_supported_band *sband;
0304     struct ieee80211_channel *ch = NULL;
0305     int i;
0306 
0307     if (!channel && !freq)
0308         return cfp;
0309 
0310     if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)
0311         sband = priv->wdev.wiphy->bands[NL80211_BAND_2GHZ];
0312     else
0313         sband = priv->wdev.wiphy->bands[NL80211_BAND_5GHZ];
0314 
0315     if (!sband) {
0316         mwifiex_dbg(priv->adapter, ERROR,
0317                 "%s: cannot find cfp by band %d\n",
0318                 __func__, band);
0319         return cfp;
0320     }
0321 
0322     for (i = 0; i < sband->n_channels; i++) {
0323         ch = &sband->channels[i];
0324 
0325         if (ch->flags & IEEE80211_CHAN_DISABLED)
0326             continue;
0327 
0328         if (freq) {
0329             if (ch->center_freq == freq)
0330                 break;
0331         } else {
0332             /* find by valid channel*/
0333             if (ch->hw_value == channel ||
0334                 channel == FIRST_VALID_CHANNEL)
0335                 break;
0336         }
0337     }
0338     if (i == sband->n_channels) {
0339         mwifiex_dbg(priv->adapter, WARN,
0340                 "%s: cannot find cfp by band %d\t"
0341                 "& channel=%d freq=%d\n",
0342                 __func__, band, channel, freq);
0343     } else {
0344         if (!ch)
0345             return cfp;
0346 
0347         priv->cfp.channel = ch->hw_value;
0348         priv->cfp.freq = ch->center_freq;
0349         priv->cfp.max_tx_power = ch->max_power;
0350         cfp = &priv->cfp;
0351     }
0352 
0353     return cfp;
0354 }
0355 
0356 /*
0357  * This function checks if the data rate is set to auto.
0358  */
0359 u8
0360 mwifiex_is_rate_auto(struct mwifiex_private *priv)
0361 {
0362     u32 i;
0363     int rate_num = 0;
0364 
0365     for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++)
0366         if (priv->bitmap_rates[i])
0367             rate_num++;
0368 
0369     if (rate_num > 1)
0370         return true;
0371     else
0372         return false;
0373 }
0374 
0375 /* This function gets the supported data rates from bitmask inside
0376  * cfg80211_scan_request.
0377  */
0378 u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,
0379                     u8 *rates, u8 radio_type)
0380 {
0381     struct wiphy *wiphy = priv->adapter->wiphy;
0382     struct cfg80211_scan_request *request = priv->scan_request;
0383     u32 num_rates, rate_mask;
0384     struct ieee80211_supported_band *sband;
0385     int i;
0386 
0387     if (radio_type) {
0388         sband = wiphy->bands[NL80211_BAND_5GHZ];
0389         if (WARN_ON_ONCE(!sband))
0390             return 0;
0391         rate_mask = request->rates[NL80211_BAND_5GHZ];
0392     } else {
0393         sband = wiphy->bands[NL80211_BAND_2GHZ];
0394         if (WARN_ON_ONCE(!sband))
0395             return 0;
0396         rate_mask = request->rates[NL80211_BAND_2GHZ];
0397     }
0398 
0399     num_rates = 0;
0400     for (i = 0; i < sband->n_bitrates; i++) {
0401         if ((BIT(i) & rate_mask) == 0)
0402             continue; /* skip rate */
0403         rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5);
0404     }
0405 
0406     return num_rates;
0407 }
0408 
0409 /* This function gets the supported data rates. The function works in
0410  * both Ad-Hoc and infra mode by printing the band and returning the
0411  * data rates.
0412  */
0413 u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
0414 {
0415     u32 k = 0;
0416     struct mwifiex_adapter *adapter = priv->adapter;
0417 
0418     if (priv->bss_mode == NL80211_IFTYPE_STATION ||
0419         priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
0420         switch (adapter->config_bands) {
0421         case BAND_B:
0422             mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
0423                     "supported_rates_b\n",
0424                     adapter->config_bands);
0425             k = mwifiex_copy_rates(rates, k, supported_rates_b,
0426                            sizeof(supported_rates_b));
0427             break;
0428         case BAND_G:
0429         case BAND_G | BAND_GN:
0430             mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
0431                     "supported_rates_g\n",
0432                     adapter->config_bands);
0433             k = mwifiex_copy_rates(rates, k, supported_rates_g,
0434                            sizeof(supported_rates_g));
0435             break;
0436         case BAND_B | BAND_G:
0437         case BAND_A | BAND_B | BAND_G:
0438         case BAND_A | BAND_B:
0439         case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
0440         case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
0441         case BAND_B | BAND_G | BAND_GN:
0442             mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
0443                     "supported_rates_bg\n",
0444                     adapter->config_bands);
0445             k = mwifiex_copy_rates(rates, k, supported_rates_bg,
0446                            sizeof(supported_rates_bg));
0447             break;
0448         case BAND_A:
0449         case BAND_A | BAND_G:
0450             mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
0451                     "supported_rates_a\n",
0452                     adapter->config_bands);
0453             k = mwifiex_copy_rates(rates, k, supported_rates_a,
0454                            sizeof(supported_rates_a));
0455             break;
0456         case BAND_AN:
0457         case BAND_A | BAND_AN:
0458         case BAND_A | BAND_AN | BAND_AAC:
0459         case BAND_A | BAND_G | BAND_AN | BAND_GN:
0460         case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
0461             mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
0462                     "supported_rates_a\n",
0463                     adapter->config_bands);
0464             k = mwifiex_copy_rates(rates, k, supported_rates_a,
0465                            sizeof(supported_rates_a));
0466             break;
0467         case BAND_GN:
0468             mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"
0469                     "supported_rates_n\n",
0470                     adapter->config_bands);
0471             k = mwifiex_copy_rates(rates, k, supported_rates_n,
0472                            sizeof(supported_rates_n));
0473             break;
0474         }
0475     } else {
0476         /* Ad-hoc mode */
0477         switch (adapter->adhoc_start_band) {
0478         case BAND_B:
0479             mwifiex_dbg(adapter, INFO, "info: adhoc B\n");
0480             k = mwifiex_copy_rates(rates, k, adhoc_rates_b,
0481                            sizeof(adhoc_rates_b));
0482             break;
0483         case BAND_G:
0484         case BAND_G | BAND_GN:
0485             mwifiex_dbg(adapter, INFO, "info: adhoc G only\n");
0486             k = mwifiex_copy_rates(rates, k, adhoc_rates_g,
0487                            sizeof(adhoc_rates_g));
0488             break;
0489         case BAND_B | BAND_G:
0490         case BAND_B | BAND_G | BAND_GN:
0491             mwifiex_dbg(adapter, INFO, "info: adhoc BG\n");
0492             k = mwifiex_copy_rates(rates, k, adhoc_rates_bg,
0493                            sizeof(adhoc_rates_bg));
0494             break;
0495         case BAND_A:
0496         case BAND_A | BAND_AN:
0497             mwifiex_dbg(adapter, INFO, "info: adhoc A\n");
0498             k = mwifiex_copy_rates(rates, k, adhoc_rates_a,
0499                            sizeof(adhoc_rates_a));
0500             break;
0501         }
0502     }
0503 
0504     return k;
0505 }
0506 
0507 u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,
0508                 u8 rx_rate, u8 rate_info)
0509 {
0510     u8 rate_index = 0;
0511 
0512     /* HT40 */
0513     if ((rate_info & BIT(0)) && (rate_info & BIT(1)))
0514         rate_index = MWIFIEX_RATE_INDEX_MCS0 +
0515                  MWIFIEX_BW20_MCS_NUM + rx_rate;
0516     else if (rate_info & BIT(0)) /* HT20 */
0517         rate_index = MWIFIEX_RATE_INDEX_MCS0 + rx_rate;
0518     else
0519         rate_index = (rx_rate > MWIFIEX_RATE_INDEX_OFDM0) ?
0520                   rx_rate - 1 : rx_rate;
0521 
0522     if (rate_index >= MWIFIEX_MAX_AC_RX_RATES)
0523         rate_index = MWIFIEX_MAX_AC_RX_RATES - 1;
0524 
0525     return rate_index;
0526 }