brintos

brintos / linux-shallow public Read only

0
0
Text · 13.7 KiB · d39092b Raw
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