0001
0002
0003
0004
0005
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
0016 #define MWIFIEX_TX_PWR_DEFAULT 20
0017
0018 #define MWIFIEX_TX_PWR_US_DEFAULT 20
0019
0020 #define MWIFIEX_TX_PWR_JP_DEFAULT 16
0021
0022 #define MWIFIEX_TX_PWR_FR_100MW 20
0023
0024 #define MWIFIEX_TX_PWR_FR_10MW 10
0025
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
0063
0064
0065 static const u16 mcs_rate[4][16] = {
0066
0067 { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
0068 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
0069
0070
0071 { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
0072 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
0073
0074
0075 { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
0076 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
0077
0078
0079 { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
0080 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
0081 };
0082
0083
0084 static const u16 ac_mcs_rate_nss1[8][10] = {
0085
0086 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
0087 0x492, 0x57C, 0x618 },
0088
0089
0090 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
0091 0x514, 0x618, 0x6C6 },
0092
0093
0094 { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,
0095 0x249, 0x2BE, 0x30C },
0096
0097
0098 { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,
0099 0x28A, 0x30C, 0x363 },
0100
0101
0102 { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
0103 0x10E, 0x144, 0x168 },
0104
0105
0106 { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,
0107 0x12C, 0x168, 0x190 },
0108
0109
0110 { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },
0111
0112
0113 { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },
0114 };
0115
0116
0117 static const u16 ac_mcs_rate_nss2[8][10] = {
0118
0119 { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,
0120 0x924, 0xAF8, 0xC30 },
0121
0122
0123 { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,
0124 0xA28, 0xC30, 0xD8B },
0125
0126
0127 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
0128 0x492, 0x57C, 0x618 },
0129
0130
0131 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
0132 0x514, 0x618, 0x6C6 },
0133
0134
0135 { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,
0136 0x21C, 0x288, 0x2D0 },
0137
0138
0139 { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,
0140 0x258, 0x2D0, 0x320 },
0141
0142
0143 { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,
0144 0x138, 0x00 },
0145
0146
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 " },
0158 { 0x20, "CA " },
0159 { 0x30, "FR " },
0160 { 0x31, "ES " },
0161 { 0x32, "FR " },
0162 { 0x40, "JP " },
0163 { 0x41, "JP " },
0164 { 0x50, "CN " },
0165 };
0166
0167
0168 u8 *mwifiex_11d_code_2_region(u8 code)
0169 {
0170 u8 i;
0171
0172
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
0182
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
0196 bw = (ht_info & 0xC) >> 2;
0197
0198
0199 gi = (ht_info & 0x10) >> 4;
0200
0201 if ((index >> 4) == 1)
0202 rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
0203 else
0204 rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
0205 } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) {
0206
0207 bw = (ht_info & 0xC) >> 2;
0208
0209
0210 gi = (ht_info & 0x10) >> 4;
0211
0212 if (index == MWIFIEX_RATE_BITMAP_MCS0) {
0213 if (gi == 1)
0214 rate = 0x0D;
0215 else
0216 rate = 0x0C;
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
0227 if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
0228 index = 0;
0229 rate = mwifiex_data_rates[index];
0230 }
0231
0232 return rate;
0233 }
0234
0235
0236
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;
0252 else
0253 rate = 0x0C;
0254 } else if (index < mcs_num_supp) {
0255 if (ht_info & BIT(1)) {
0256 if (ht_info & BIT(2))
0257
0258 rate = mcs_rate[1][index];
0259 else
0260
0261 rate = mcs_rate[0][index];
0262 } else {
0263 if (ht_info & BIT(2))
0264
0265 rate = mcs_rate[3][index];
0266 else
0267
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
0282
0283
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
0297
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
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
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
0376
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;
0403 rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5);
0404 }
0405
0406 return num_rates;
0407 }
0408
0409
0410
0411
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
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
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))
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 }