527 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * NXP Wireless LAN device driver: Channel, Frequence and Power4 *5 * Copyright 2011-2020 NXP6 */7 8#include "decl.h"9#include "ioctl.h"10#include "util.h"11#include "fw.h"12#include "main.h"13#include "cfg80211.h"14 15/* 100mW */16#define MWIFIEX_TX_PWR_DEFAULT 2017/* 100mW */18#define MWIFIEX_TX_PWR_US_DEFAULT 2019/* 50mW */20#define MWIFIEX_TX_PWR_JP_DEFAULT 1621/* 100mW */22#define MWIFIEX_TX_PWR_FR_100MW 2023/* 10mW */24#define MWIFIEX_TX_PWR_FR_10MW 1025/* 100mW */26#define MWIFIEX_TX_PWR_EMEA_DEFAULT 2027 28static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 };29 30static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,31 0xb0, 0x48, 0x60, 0x6c, 0 };32 33static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96,34 0x0c, 0x12, 0x18, 0x24,35 0x30, 0x48, 0x60, 0x6c, 0 };36 37static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24,38 0xb0, 0x48, 0x60, 0x6c, 0 };39static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,40 0xb0, 0x48, 0x60, 0x6c, 0 };41static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04,42 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18,43 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90,44 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68,45 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51,46 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 };47 48static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 };49 50static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24,51 0x30, 0x48, 0x60, 0x6c, 0 };52 53static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,54 0x12, 0x16, 0x18, 0x24, 0x30, 0x48,55 0x60, 0x6c, 0 };56 57u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x00, 0x10, 0x20, 0x30,58 0x31, 0x32, 0x40, 0x41, 0x50 };59 60static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };61 62/* For every mcs_rate line, the first 8 bytes are for stream 1x1,63 * and all 16 bytes are for stream 2x2.64 */65static const u16 mcs_rate[4][16] = {66 /* LGI 40M */67 { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,68 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },69 70 /* SGI 40M */71 { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,72 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },73 74 /* LGI 20M */75 { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,76 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },77 78 /* SGI 20M */79 { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,80 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }81};82 83/* AC rates */84static const u16 ac_mcs_rate_nss1[8][10] = {85 /* LG 160M */86 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,87 0x492, 0x57C, 0x618 },88 89 /* SG 160M */90 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,91 0x514, 0x618, 0x6C6 },92 93 /* LG 80M */94 { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,95 0x249, 0x2BE, 0x30C },96 97 /* SG 80M */98 { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,99 0x28A, 0x30C, 0x363 },100 101 /* LG 40M */102 { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,103 0x10E, 0x144, 0x168 },104 105 /* SG 40M */106 { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,107 0x12C, 0x168, 0x190 },108 109 /* LG 20M */110 { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },111 112 /* SG 20M */113 { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },114};115 116/* NSS2 note: the value in the table is 2 multiplier of the actual rate */117static const u16 ac_mcs_rate_nss2[8][10] = {118 /* LG 160M */119 { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,120 0x924, 0xAF8, 0xC30 },121 122 /* SG 160M */123 { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,124 0xA28, 0xC30, 0xD8B },125 126 /* LG 80M */127 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,128 0x492, 0x57C, 0x618 },129 130 /* SG 80M */131 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,132 0x514, 0x618, 0x6C6 },133 134 /* LG 40M */135 { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,136 0x21C, 0x288, 0x2D0 },137 138 /* SG 40M */139 { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,140 0x258, 0x2D0, 0x320 },141 142 /* LG 20M */143 { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,144 0x138, 0x00 },145 146 /* SG 20M */147 { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121,148 0x15B, 0x00 },149};150 151struct region_code_mapping {152 u8 code;153 u8 region[IEEE80211_COUNTRY_STRING_LEN];154};155 156static struct region_code_mapping region_code_mapping_t[] = {157 { 0x10, "US " }, /* US FCC */158 { 0x20, "CA " }, /* IC Canada */159 { 0x30, "FR " }, /* France */160 { 0x31, "ES " }, /* Spain */161 { 0x32, "FR " }, /* France */162 { 0x40, "JP " }, /* Japan */163 { 0x41, "JP " }, /* Japan */164 { 0x50, "CN " }, /* China */165};166 167/* This function converts integer code to region string */168u8 *mwifiex_11d_code_2_region(u8 code)169{170 u8 i;171 172 /* Look for code in mapping table */173 for (i = 0; i < ARRAY_SIZE(region_code_mapping_t); i++)174 if (region_code_mapping_t[i].code == code)175 return region_code_mapping_t[i].region;176 177 return NULL;178}179 180/*181 * This function maps an index in supported rates table into182 * the corresponding data rate.183 */184u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,185 u8 index, u8 ht_info)186{187 u32 rate = 0;188 u8 mcs_index = 0;189 u8 bw = 0;190 u8 gi = 0;191 192 if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) {193 mcs_index = min(index & 0xF, 9);194 195 /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */196 bw = (ht_info & 0xC) >> 2;197 198 /* LGI: gi =0, SGI: gi = 1 */199 gi = (ht_info & 0x10) >> 4;200 201 if ((index >> 4) == 1) /* NSS = 2 */202 rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];203 else /* NSS = 1 */204 rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];205 } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) {206 /* 20M: bw=0, 40M: bw=1 */207 bw = (ht_info & 0xC) >> 2;208 209 /* LGI: gi =0, SGI: gi = 1 */210 gi = (ht_info & 0x10) >> 4;211 212 if (index == MWIFIEX_RATE_BITMAP_MCS0) {213 if (gi == 1)214 rate = 0x0D; /* MCS 32 SGI rate */215 else216 rate = 0x0C; /* MCS 32 LGI rate */217 } else if (index < 16) {218 if ((bw == 1) || (bw == 0))219 rate = mcs_rate[2 * (1 - bw) + gi][index];220 else221 rate = mwifiex_data_rates[0];222 } else {223 rate = mwifiex_data_rates[0];224 }225 } else {226 /* 11n non-HT rates */227 if (index >= MWIFIEX_SUPPORTED_RATES_EXT)228 index = 0;229 rate = mwifiex_data_rates[index];230 }231 232 return rate;233}234 235/* This function maps an index in supported rates table into236 * the corresponding data rate.237 */238u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,239 u8 index, u8 ht_info)240{241 u32 mcs_num_supp =242 (priv->adapter->user_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;243 u32 rate;244 245 if (priv->adapter->is_hw_11ac_capable)246 return mwifiex_index_to_acs_data_rate(priv, index, ht_info);247 248 if (ht_info & BIT(0)) {249 if (index == MWIFIEX_RATE_BITMAP_MCS0) {250 if (ht_info & BIT(2))251 rate = 0x0D; /* MCS 32 SGI rate */252 else253 rate = 0x0C; /* MCS 32 LGI rate */254 } else if (index < mcs_num_supp) {255 if (ht_info & BIT(1)) {256 if (ht_info & BIT(2))257 /* SGI, 40M */258 rate = mcs_rate[1][index];259 else260 /* LGI, 40M */261 rate = mcs_rate[0][index];262 } else {263 if (ht_info & BIT(2))264 /* SGI, 20M */265 rate = mcs_rate[3][index];266 else267 /* LGI, 20M */268 rate = mcs_rate[2][index];269 }270 } else271 rate = mwifiex_data_rates[0];272 } else {273 if (index >= MWIFIEX_SUPPORTED_RATES_EXT)274 index = 0;275 rate = mwifiex_data_rates[index];276 }277 return rate;278}279 280/*281 * This function returns the current active data rates.282 *283 * The result may vary depending upon connection status.284 */285u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates)286{287 if (!priv->media_connected)288 return mwifiex_get_supported_rates(priv, rates);289 else290 return mwifiex_copy_rates(rates, 0,291 priv->curr_bss_params.data_rates,292 priv->curr_bss_params.num_of_rates);293}294 295/*296 * This function locates the Channel-Frequency-Power triplet based upon297 * band and channel/frequency parameters.298 */299struct mwifiex_chan_freq_power *300mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq)301{302 struct mwifiex_chan_freq_power *cfp = NULL;303 struct ieee80211_supported_band *sband;304 struct ieee80211_channel *ch = NULL;305 int i;306 307 if (!channel && !freq)308 return cfp;309 310 if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG)311 sband = priv->wdev.wiphy->bands[NL80211_BAND_2GHZ];312 else313 sband = priv->wdev.wiphy->bands[NL80211_BAND_5GHZ];314 315 if (!sband) {316 mwifiex_dbg(priv->adapter, ERROR,317 "%s: cannot find cfp by band %d\n",318 __func__, band);319 return cfp;320 }321 322 for (i = 0; i < sband->n_channels; i++) {323 ch = &sband->channels[i];324 325 if (ch->flags & IEEE80211_CHAN_DISABLED)326 continue;327 328 if (freq) {329 if (ch->center_freq == freq)330 break;331 } else {332 /* find by valid channel*/333 if (ch->hw_value == channel ||334 channel == FIRST_VALID_CHANNEL)335 break;336 }337 }338 if (i == sband->n_channels) {339 mwifiex_dbg(priv->adapter, WARN,340 "%s: cannot find cfp by band %d\t"341 "& channel=%d freq=%d\n",342 __func__, band, channel, freq);343 } else {344 if (!ch)345 return cfp;346 347 priv->cfp.channel = ch->hw_value;348 priv->cfp.freq = ch->center_freq;349 priv->cfp.max_tx_power = ch->max_power;350 cfp = &priv->cfp;351 }352 353 return cfp;354}355 356/*357 * This function checks if the data rate is set to auto.358 */359u8360mwifiex_is_rate_auto(struct mwifiex_private *priv)361{362 u32 i;363 int rate_num = 0;364 365 for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++)366 if (priv->bitmap_rates[i])367 rate_num++;368 369 if (rate_num > 1)370 return true;371 else372 return false;373}374 375/* This function gets the supported data rates from bitmask inside376 * cfg80211_scan_request.377 */378u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv,379 u8 *rates, u8 radio_type)380{381 struct wiphy *wiphy = priv->adapter->wiphy;382 struct cfg80211_scan_request *request = priv->scan_request;383 u32 num_rates, rate_mask;384 struct ieee80211_supported_band *sband;385 int i;386 387 if (radio_type) {388 sband = wiphy->bands[NL80211_BAND_5GHZ];389 if (WARN_ON_ONCE(!sband))390 return 0;391 rate_mask = request->rates[NL80211_BAND_5GHZ];392 } else {393 sband = wiphy->bands[NL80211_BAND_2GHZ];394 if (WARN_ON_ONCE(!sband))395 return 0;396 rate_mask = request->rates[NL80211_BAND_2GHZ];397 }398 399 num_rates = 0;400 for (i = 0; i < sband->n_bitrates; i++) {401 if ((BIT(i) & rate_mask) == 0)402 continue; /* skip rate */403 rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5);404 }405 406 return num_rates;407}408 409/* This function gets the supported data rates. The function works in410 * both Ad-Hoc and infra mode by printing the band and returning the411 * data rates.412 */413u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)414{415 u32 k = 0;416 struct mwifiex_adapter *adapter = priv->adapter;417 418 if (priv->bss_mode == NL80211_IFTYPE_STATION ||419 priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {420 switch (adapter->config_bands) {421 case BAND_B:422 mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"423 "supported_rates_b\n",424 adapter->config_bands);425 k = mwifiex_copy_rates(rates, k, supported_rates_b,426 sizeof(supported_rates_b));427 break;428 case BAND_G:429 case BAND_G | BAND_GN:430 mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"431 "supported_rates_g\n",432 adapter->config_bands);433 k = mwifiex_copy_rates(rates, k, supported_rates_g,434 sizeof(supported_rates_g));435 break;436 case BAND_B | BAND_G:437 case BAND_A | BAND_B | BAND_G:438 case BAND_A | BAND_B:439 case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:440 case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:441 case BAND_B | BAND_G | BAND_GN:442 mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"443 "supported_rates_bg\n",444 adapter->config_bands);445 k = mwifiex_copy_rates(rates, k, supported_rates_bg,446 sizeof(supported_rates_bg));447 break;448 case BAND_A:449 case BAND_A | BAND_G:450 mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"451 "supported_rates_a\n",452 adapter->config_bands);453 k = mwifiex_copy_rates(rates, k, supported_rates_a,454 sizeof(supported_rates_a));455 break;456 case BAND_AN:457 case BAND_A | BAND_AN:458 case BAND_A | BAND_AN | BAND_AAC:459 case BAND_A | BAND_G | BAND_AN | BAND_GN:460 case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:461 mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"462 "supported_rates_a\n",463 adapter->config_bands);464 k = mwifiex_copy_rates(rates, k, supported_rates_a,465 sizeof(supported_rates_a));466 break;467 case BAND_GN:468 mwifiex_dbg(adapter, INFO, "info: infra band=%d\t"469 "supported_rates_n\n",470 adapter->config_bands);471 k = mwifiex_copy_rates(rates, k, supported_rates_n,472 sizeof(supported_rates_n));473 break;474 }475 } else {476 /* Ad-hoc mode */477 switch (adapter->adhoc_start_band) {478 case BAND_B:479 mwifiex_dbg(adapter, INFO, "info: adhoc B\n");480 k = mwifiex_copy_rates(rates, k, adhoc_rates_b,481 sizeof(adhoc_rates_b));482 break;483 case BAND_G:484 case BAND_G | BAND_GN:485 mwifiex_dbg(adapter, INFO, "info: adhoc G only\n");486 k = mwifiex_copy_rates(rates, k, adhoc_rates_g,487 sizeof(adhoc_rates_g));488 break;489 case BAND_B | BAND_G:490 case BAND_B | BAND_G | BAND_GN:491 mwifiex_dbg(adapter, INFO, "info: adhoc BG\n");492 k = mwifiex_copy_rates(rates, k, adhoc_rates_bg,493 sizeof(adhoc_rates_bg));494 break;495 case BAND_A:496 case BAND_A | BAND_AN:497 mwifiex_dbg(adapter, INFO, "info: adhoc A\n");498 k = mwifiex_copy_rates(rates, k, adhoc_rates_a,499 sizeof(adhoc_rates_a));500 break;501 }502 }503 504 return k;505}506 507u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv,508 u8 rx_rate, u8 rate_info)509{510 u8 rate_index = 0;511 512 /* HT40 */513 if ((rate_info & BIT(0)) && (rate_info & BIT(1)))514 rate_index = MWIFIEX_RATE_INDEX_MCS0 +515 MWIFIEX_BW20_MCS_NUM + rx_rate;516 else if (rate_info & BIT(0)) /* HT20 */517 rate_index = MWIFIEX_RATE_INDEX_MCS0 + rx_rate;518 else519 rate_index = (rx_rate > MWIFIEX_RATE_INDEX_OFDM0) ?520 rx_rate - 1 : rx_rate;521 522 if (rate_index >= MWIFIEX_MAX_AC_RX_RATES)523 rate_index = MWIFIEX_MAX_AC_RX_RATES - 1;524 525 return rate_index;526}527