1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * nxpwifi: Channel, Frequency and Power 4 * 5 * Copyright 2011-2024 NXP 6 */ 7 8 #include "cfg.h" 9 #include "util.h" 10 #include "fw.h" 11 #include "main.h" 12 #include "cfg80211.h" 13 14 /* 100mW */ 15 #define NXPWIFI_TX_PWR_DEFAULT 20 16 /* 100mW */ 17 #define NXPWIFI_TX_PWR_US_DEFAULT 20 18 /* 50mW */ 19 #define NXPWIFI_TX_PWR_JP_DEFAULT 16 20 /* 100mW */ 21 #define NXPWIFI_TX_PWR_FR_100MW 20 22 /* 10mW */ 23 #define NXPWIFI_TX_PWR_FR_10MW 10 24 /* 100mW */ 25 #define NXPWIFI_TX_PWR_EMEA_DEFAULT 20 26 27 static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, 28 0xb0, 0x48, 0x60, 0x6c, 0 }; 29 static u16 nxpwifi_data_rates[NXPWIFI_SUPPORTED_RATES_EXT] = { 0x02, 0x04, 30 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, 31 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90, 32 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, 33 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51, 34 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 }; 35 36 static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 }; 37 38 static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, 39 0x30, 0x48, 0x60, 0x6c, 0 }; 40 41 static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c, 42 0x12, 0x16, 0x18, 0x24, 0x30, 0x48, 43 0x60, 0x6c, 0 }; 44 45 /* mcs_rate: first 8 entries for 1x1; all 16 for 2x2. */ 46 static const u16 mcs_rate[4][16] = { 47 /* LGI 40M */ 48 { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 49 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c }, 50 51 /* SGI 40M */ 52 { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, 53 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 }, 54 55 /* LGI 20M */ 56 { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, 57 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 }, 58 59 /* SGI 20M */ 60 { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 61 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } 62 }; 63 64 /* AC rates */ 65 static const u16 ac_mcs_rate_nss1[8][10] = { 66 /* LG 160M */ 67 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 68 0x492, 0x57C, 0x618 }, 69 70 /* SG 160M */ 71 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 72 0x514, 0x618, 0x6C6 }, 73 74 /* LG 80M */ 75 { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, 76 0x249, 0x2BE, 0x30C }, 77 78 /* SG 80M */ 79 { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, 80 0x28A, 0x30C, 0x363 }, 81 82 /* LG 40M */ 83 { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, 84 0x10E, 0x144, 0x168 }, 85 86 /* SG 40M */ 87 { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, 88 0x12C, 0x168, 0x190 }, 89 90 /* LG 20M */ 91 { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 }, 92 93 /* SG 20M */ 94 { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 }, 95 }; 96 97 /* NSS2 note: the value in the table is 2 multiplier of the actual rate */ 98 static const u16 ac_mcs_rate_nss2[8][10] = { 99 /* LG 160M */ 100 { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, 101 0x924, 0xAF8, 0xC30 }, 102 103 /* SG 160M */ 104 { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, 105 0xA28, 0xC30, 0xD8B }, 106 107 /* LG 80M */ 108 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, 109 0x492, 0x57C, 0x618 }, 110 111 /* SG 80M */ 112 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, 113 0x514, 0x618, 0x6C6 }, 114 115 /* LG 40M */ 116 { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, 117 0x21C, 0x288, 0x2D0 }, 118 119 /* SG 40M */ 120 { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, 121 0x258, 0x2D0, 0x320 }, 122 123 /* LG 20M */ 124 { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, 125 0x138, 0x00 }, 126 127 /* SG 20M */ 128 { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, 129 0x15B, 0x00 }, 130 }; 131 132 struct region_code_mapping { 133 u8 code; 134 u8 region[IEEE80211_COUNTRY_STRING_LEN]; 135 }; 136 137 static struct region_code_mapping region_code_mapping_t[] = { 138 { 0x10, "US " }, /* US FCC */ 139 { 0x20, "CA " }, /* IC Canada */ 140 { 0x30, "FR " }, /* France */ 141 { 0x31, "ES " }, /* Spain */ 142 { 0x32, "FR " }, /* France */ 143 { 0x40, "JP " }, /* Japan */ 144 { 0x41, "JP " }, /* Japan */ 145 { 0x50, "CN " }, /* China */ 146 }; 147 148 /* Convert 11d country code to region string. */ 149 u8 *nxpwifi_11d_code_2_region(u8 code) 150 { 151 u8 i; 152 153 /* Look for code in mapping table */ 154 for (i = 0; i < ARRAY_SIZE(region_code_mapping_t); i++) 155 if (region_code_mapping_t[i].code == code) 156 return region_code_mapping_t[i].region; 157 158 return NULL; 159 } 160 161 /* Map supported rate index to AC/VHT data rate. */ 162 u32 nxpwifi_index_to_acs_data_rate(struct nxpwifi_private *priv, 163 u8 index, u8 ht_info) 164 { 165 u32 rate = 0; 166 u8 mcs_index = 0; 167 u8 bw = 0; 168 u8 gi = 0; 169 170 if ((ht_info & 0x3) == NXPWIFI_RATE_FORMAT_VHT) { 171 mcs_index = min(index & 0xF, 9); 172 173 /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */ 174 bw = (ht_info & 0xC) >> 2; 175 176 /* LGI: gi =0, SGI: gi = 1 */ 177 gi = (ht_info & 0x10) >> 4; 178 179 if ((index >> 4) == 1) /* NSS = 2 */ 180 rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index]; 181 else /* NSS = 1 */ 182 rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index]; 183 } else if ((ht_info & 0x3) == NXPWIFI_RATE_FORMAT_HT) { 184 /* 20M: bw=0, 40M: bw=1 */ 185 bw = (ht_info & 0xC) >> 2; 186 187 /* LGI: gi =0, SGI: gi = 1 */ 188 gi = (ht_info & 0x10) >> 4; 189 190 if (index == NXPWIFI_RATE_BITMAP_MCS0) { 191 if (gi == 1) 192 rate = 0x0D; /* MCS 32 SGI rate */ 193 else 194 rate = 0x0C; /* MCS 32 LGI rate */ 195 } else if (index < 16) { 196 if (bw == 1 || bw == 0) 197 rate = mcs_rate[2 * (1 - bw) + gi][index]; 198 else 199 rate = nxpwifi_data_rates[0]; 200 } else { 201 rate = nxpwifi_data_rates[0]; 202 } 203 } else { 204 /* 11n non-HT rates */ 205 if (index >= NXPWIFI_SUPPORTED_RATES_EXT) 206 index = 0; 207 rate = nxpwifi_data_rates[index]; 208 } 209 210 return rate; 211 } 212 213 /* Map supported rate index to data rate. */ 214 u32 nxpwifi_index_to_data_rate(struct nxpwifi_private *priv, 215 u8 index, u8 ht_info) 216 { 217 u32 mcs_num_supp = 218 (priv->adapter->user_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8; 219 u32 rate; 220 221 if (priv->adapter->is_hw_11ac_capable) 222 return nxpwifi_index_to_acs_data_rate(priv, index, ht_info); 223 224 if (ht_info & BIT(0)) { 225 if (index == NXPWIFI_RATE_BITMAP_MCS0) { 226 if (ht_info & BIT(2)) 227 rate = 0x0D; /* MCS 32 SGI rate */ 228 else 229 rate = 0x0C; /* MCS 32 LGI rate */ 230 } else if (index < mcs_num_supp) { 231 if (ht_info & BIT(1)) { 232 if (ht_info & BIT(2)) 233 /* SGI, 40M */ 234 rate = mcs_rate[1][index]; 235 else 236 /* LGI, 40M */ 237 rate = mcs_rate[0][index]; 238 } else { 239 if (ht_info & BIT(2)) 240 /* SGI, 20M */ 241 rate = mcs_rate[3][index]; 242 else 243 /* LGI, 20M */ 244 rate = mcs_rate[2][index]; 245 } 246 } else { 247 rate = nxpwifi_data_rates[0]; 248 } 249 } else { 250 if (index >= NXPWIFI_SUPPORTED_RATES_EXT) 251 index = 0; 252 rate = nxpwifi_data_rates[index]; 253 } 254 return rate; 255 } 256 257 /* Return current active data rates (depends on connection). */ 258 u32 nxpwifi_get_active_data_rates(struct nxpwifi_private *priv, u8 *rates) 259 { 260 if (!priv->media_connected) 261 return nxpwifi_get_supported_rates(priv, rates); 262 else 263 return nxpwifi_copy_rates(rates, 0, 264 priv->curr_bss_params.data_rates, 265 priv->curr_bss_params.num_of_rates); 266 } 267 268 /* Find Channel/Frequency/Power by band and channel or frequency. */ 269 struct nxpwifi_chan_freq_power * 270 nxpwifi_get_cfp(struct nxpwifi_private *priv, u8 band, u16 channel, u32 freq) 271 { 272 struct nxpwifi_chan_freq_power *cfp = NULL; 273 struct ieee80211_supported_band *sband; 274 struct ieee80211_channel *ch = NULL; 275 int i; 276 277 if (!channel && !freq) 278 return cfp; 279 280 if (nxpwifi_band_to_radio_type(band) == HOST_SCAN_RADIO_TYPE_BG) 281 sband = priv->wdev.wiphy->bands[NL80211_BAND_2GHZ]; 282 else 283 sband = priv->wdev.wiphy->bands[NL80211_BAND_5GHZ]; 284 285 if (!sband) { 286 nxpwifi_dbg(priv->adapter, ERROR, 287 "%s: cannot find cfp by band %d\n", 288 __func__, band); 289 return cfp; 290 } 291 292 for (i = 0; i < sband->n_channels; i++) { 293 ch = &sband->channels[i]; 294 295 if (ch->flags & IEEE80211_CHAN_DISABLED) 296 continue; 297 298 if (freq) { 299 if (ch->center_freq == freq) 300 break; 301 } else { 302 /* Find by valid channel. */ 303 if (ch->hw_value == channel || 304 channel == FIRST_VALID_CHANNEL) 305 break; 306 } 307 } 308 if (i == sband->n_channels) { 309 nxpwifi_dbg(priv->adapter, WARN, 310 "%s: cannot find cfp by band %d\t" 311 "& channel=%d freq=%d\n", 312 __func__, band, channel, freq); 313 } else { 314 if (!ch) 315 return cfp; 316 317 priv->cfp.channel = ch->hw_value; 318 priv->cfp.freq = ch->center_freq; 319 priv->cfp.max_tx_power = ch->max_power; 320 cfp = &priv->cfp; 321 } 322 323 return cfp; 324 } 325 326 /* Return true if data rate is set to auto. */ 327 u8 328 nxpwifi_is_rate_auto(struct nxpwifi_private *priv) 329 { 330 u32 i; 331 int rate_num = 0; 332 333 for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++) 334 if (priv->bitmap_rates[i]) 335 rate_num++; 336 337 if (rate_num > 1) 338 return true; 339 else 340 return false; 341 } 342 343 /* Extract supported rates from cfg80211_scan_request bitmask. */ 344 u32 nxpwifi_get_rates_from_cfg80211(struct nxpwifi_private *priv, 345 u8 *rates, u8 radio_type) 346 { 347 struct wiphy *wiphy = priv->adapter->wiphy; 348 struct cfg80211_scan_request *request = priv->scan_request; 349 u32 num_rates, rate_mask; 350 struct ieee80211_supported_band *sband; 351 int i; 352 353 if (radio_type) { 354 sband = wiphy->bands[NL80211_BAND_5GHZ]; 355 if (WARN_ON_ONCE(!sband)) 356 return 0; 357 rate_mask = request->rates[NL80211_BAND_5GHZ]; 358 } else { 359 sband = wiphy->bands[NL80211_BAND_2GHZ]; 360 if (WARN_ON_ONCE(!sband)) 361 return 0; 362 rate_mask = request->rates[NL80211_BAND_2GHZ]; 363 } 364 365 num_rates = 0; 366 for (i = 0; i < sband->n_bitrates; i++) { 367 if ((BIT(i) & rate_mask) == 0) 368 continue; /* skip rate */ 369 rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5); 370 } 371 372 return num_rates; 373 } 374 375 /* Convert config_bands to B/G/A band */ 376 static u16 nxpwifi_convert_config_bands(u16 config_bands) 377 { 378 u16 bands = 0; 379 380 if (config_bands & BAND_B) 381 bands |= BAND_B; 382 if (config_bands & BAND_G || config_bands & BAND_GN || 383 config_bands & BAND_GAC || config_bands & BAND_GAX) 384 bands |= BAND_G; 385 if (config_bands & BAND_A || config_bands & BAND_AN || 386 config_bands & BAND_AAC || config_bands & BAND_AAX) 387 bands |= BAND_A; 388 389 return bands; 390 } 391 392 /* Get supported rates in infrastructure (STA/P2P client) mode. */ 393 u32 nxpwifi_get_supported_rates(struct nxpwifi_private *priv, u8 *rates) 394 { 395 struct nxpwifi_adapter *adapter = priv->adapter; 396 u32 k = 0; 397 u16 bands = 0; 398 399 bands = nxpwifi_convert_config_bands(adapter->fw_bands); 400 401 if (priv->bss_mode == NL80211_IFTYPE_STATION) { 402 if (bands == BAND_B) { 403 /* B only */ 404 nxpwifi_dbg(adapter, INFO, "info: infra band=%d\t" 405 "supported_rates_b\n", 406 priv->config_bands); 407 k = nxpwifi_copy_rates(rates, k, supported_rates_b, 408 sizeof(supported_rates_b)); 409 } else if (bands == BAND_G) { 410 /* G only */ 411 nxpwifi_dbg(adapter, INFO, "info: infra band=%d\t" 412 "supported_rates_g\n", 413 priv->config_bands); 414 k = nxpwifi_copy_rates(rates, k, supported_rates_g, 415 sizeof(supported_rates_g)); 416 } else if (bands & (BAND_B | BAND_G)) { 417 /* BG only */ 418 nxpwifi_dbg(adapter, INFO, "info: infra band=%d\t" 419 "supported_rates_bg\n", 420 priv->config_bands); 421 k = nxpwifi_copy_rates(rates, k, supported_rates_bg, 422 sizeof(supported_rates_bg)); 423 } else if (bands & BAND_A) { 424 /* support A */ 425 nxpwifi_dbg(adapter, INFO, "info: infra band=%d\t" 426 "supported_rates_a\n", 427 priv->config_bands); 428 k = nxpwifi_copy_rates(rates, k, supported_rates_a, 429 sizeof(supported_rates_a)); 430 } 431 } 432 433 return k; 434 } 435 436 u8 nxpwifi_adjust_data_rate(struct nxpwifi_private *priv, 437 u8 rx_rate, u8 rate_info) 438 { 439 u8 rate_index = 0; 440 441 /* HT40 */ 442 if ((rate_info & BIT(0)) && (rate_info & BIT(1))) 443 rate_index = NXPWIFI_RATE_INDEX_MCS0 + 444 NXPWIFI_BW20_MCS_NUM + rx_rate; 445 else if (rate_info & BIT(0)) /* HT20 */ 446 rate_index = NXPWIFI_RATE_INDEX_MCS0 + rx_rate; 447 else 448 rate_index = (rx_rate > NXPWIFI_RATE_INDEX_OFDM0) ? 449 rx_rate - 1 : rx_rate; 450 451 if (rate_index >= NXPWIFI_MAX_AC_RX_RATES) 452 rate_index = NXPWIFI_MAX_AC_RX_RATES - 1; 453 454 return rate_index; 455 } 456 457 /* Check if the given region code is a valid NXP-defined region code. 458 * Valid codes are defined by the FW v18 region enum in IEEE_types.h: 459 * 0x00 (World), 0x10 (US/FCC), 0x20 (Canada/IC), 0x30 (ETSI), 460 * 0x31 (Spain), 0x32 (France), 0x40 (Japan), 0x41 (Japan1), 0x50 (China) 461 */ 462 bool nxpwifi_is_valid_region_code(enum nxpwifi_region_code code) 463 { 464 switch (code) { 465 case NXPWIFI_REGION_WORLD: 466 case NXPWIFI_REGION_FCC: 467 case NXPWIFI_REGION_IC: 468 case NXPWIFI_REGION_ETSI: 469 case NXPWIFI_REGION_SPAIN: 470 case NXPWIFI_REGION_FRANCE: 471 case NXPWIFI_REGION_JAPAN: 472 case NXPWIFI_REGION_JAPAN1: 473 case NXPWIFI_REGION_CHINA: 474 return true; 475 default: 476 return false; 477 } 478 } 479