diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/cfp.c')
| -rw-r--r-- | drivers/net/wireless/mwifiex/cfp.c | 159 | 
1 files changed, 157 insertions, 2 deletions
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index f69300f93f4..988552dece7 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c @@ -106,8 +106,8 @@ u8 *mwifiex_11d_code_2_region(u8 code)   * This function maps an index in supported rates table into   * the corresponding data rate.   */ -u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index, -							u8 ht_info) +u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, +				   u8 index, u8 ht_info)  {  	/*  	 * For every mcs_rate line, the first 8 bytes are for stream 1x1, @@ -130,10 +130,155 @@ u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index,  		{ 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,  		  0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }  	}; +	/* AC rates */ +	u16 ac_mcs_rate_nss1[8][10] = { +		/* LG 160M */ +		{ 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, +		  0x492, 0x57C, 0x618 }, + +		/* SG 160M */ +		{ 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, +		  0x514, 0x618, 0x6C6 }, + +		/* LG 80M */ +		{ 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, +		  0x249, 0x2BE, 0x30C }, + +		/* SG 80M */ +		{ 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, +		  0x28A, 0x30C, 0x363 }, + +		/* LG 40M */ +		{ 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, +		  0x10E, 0x144, 0x168 }, + +		/* SG 40M */ +		{ 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, +		  0x12C, 0x168, 0x190 }, + +		/* LG 20M */ +		{ 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 }, + +		/* SG 20M */ +		{ 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 }, +	}; +	/* NSS2 note: the value in the table is 2 multiplier of the actual +	 * rate +	 */ +	u16 ac_mcs_rate_nss2[8][10] = { +		/* LG 160M */ +		{ 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, +		  0x924, 0xAF8, 0xC30 }, + +		/* SG 160M */ +		{ 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, +		  0xA28, 0xC30, 0xD8B }, + +		/* LG 80M */ +		{ 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, +		  0x492, 0x57C, 0x618 }, + +		/* SG 80M */ +		{ 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, +		  0x514, 0x618, 0x6C6 }, + +		/* LG 40M */ +		{ 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, +		  0x21C, 0x288, 0x2D0 }, + +		/* SG 40M */ +		{ 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, +		  0x258, 0x2D0, 0x320 }, + +		/* LG 20M */ +		{ 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, +		  0x138, 0x00 }, + +		/* SG 20M */ +		{ 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, +		  0x15B, 0x00 }, +	}; +	u32 rate = 0; +	u8 mcs_index = 0; +	u8 bw = 0; +	u8 gi = 0; + +	if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) { +		mcs_index = min(index & 0xF, 9); + +		/* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */ +		bw = (ht_info & 0xC) >> 2; + +		/* LGI: gi =0, SGI: gi = 1 */ +		gi = (ht_info & 0x10) >> 4; + +		if ((index >> 4) == 1)	/* NSS = 2 */ +			rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index]; +		else			/* NSS = 1 */ +			rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index]; +	} else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) { +		/* 20M: bw=0, 40M: bw=1 */ +		bw = (ht_info & 0xC) >> 2; + +		/* LGI: gi =0, SGI: gi = 1 */ +		gi = (ht_info & 0x10) >> 4; + +		if (index == MWIFIEX_RATE_BITMAP_MCS0) { +			if (gi == 1) +				rate = 0x0D;    /* MCS 32 SGI rate */ +			else +				rate = 0x0C;    /* MCS 32 LGI rate */ +		} else if (index < 16) { +			if ((bw == 1) || (bw == 0)) +				rate = mcs_rate[2 * (1 - bw) + gi][index]; +			else +				rate = mwifiex_data_rates[0]; +		} else { +			rate = mwifiex_data_rates[0]; +		} +	} else { +		/* 11n non-HT rates */ +		if (index >= MWIFIEX_SUPPORTED_RATES_EXT) +			index = 0; +		rate = mwifiex_data_rates[index]; +	} + +	return rate; +} + +/* This function maps an index in supported rates table into + * the corresponding data rate. + */ +u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, +			       u8 index, u8 ht_info) +{ +	/* For every mcs_rate line, the first 8 bytes are for stream 1x1, +	 * and all 16 bytes are for stream 2x2. +	 */ +	u16  mcs_rate[4][16] = { +		/* LGI 40M */ +		{ 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, +		  0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c }, + +		/* SGI 40M */ +		{ 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, +		  0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 }, + +		/* LGI 20M */ +		{ 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, +		  0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 }, + +		/* SGI 20M */ +		{ 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, +		  0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } +	};  	u32 mcs_num_supp =  		(priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;  	u32 rate; +	if (priv->adapter->is_hw_11ac_capable) +		return mwifiex_index_to_acs_data_rate(priv, index, ht_info); +  	if (ht_info & BIT(0)) {  		if (index == MWIFIEX_RATE_BITMAP_MCS0) {  			if (ht_info & BIT(2)) @@ -269,6 +414,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)  {  	u32 k = 0;  	struct mwifiex_adapter *adapter = priv->adapter; +  	if (priv->bss_mode == NL80211_IFTYPE_STATION) {  		switch (adapter->config_bands) {  		case BAND_B: @@ -279,6 +425,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)  			break;  		case BAND_G:  		case BAND_G | BAND_GN: +		case BAND_G | BAND_GN | BAND_GAC:  			dev_dbg(adapter->dev, "info: infra band=%d "  				"supported_rates_g\n", adapter->config_bands);  			k = mwifiex_copy_rates(rates, k, supported_rates_g, @@ -288,7 +435,11 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)  		case BAND_A | BAND_B | BAND_G:  		case BAND_A | BAND_B:  		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: +		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC: +		case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | +		     BAND_AAC | BAND_GAC:  		case BAND_B | BAND_G | BAND_GN: +		case BAND_B | BAND_G | BAND_GN | BAND_GAC:  			dev_dbg(adapter->dev, "info: infra band=%d "  				"supported_rates_bg\n", adapter->config_bands);  			k = mwifiex_copy_rates(rates, k, supported_rates_bg, @@ -301,14 +452,18 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)  			k = mwifiex_copy_rates(rates, k, supported_rates_a,  					       sizeof(supported_rates_a));  			break; +		case BAND_AN:  		case BAND_A | BAND_AN: +		case BAND_A | BAND_AN | BAND_AAC:  		case BAND_A | BAND_G | BAND_AN | BAND_GN: +		case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:  			dev_dbg(adapter->dev, "info: infra band=%d "  				"supported_rates_a\n", adapter->config_bands);  			k = mwifiex_copy_rates(rates, k, supported_rates_a,  					       sizeof(supported_rates_a));  			break;  		case BAND_GN: +		case BAND_GN | BAND_GAC:  			dev_dbg(adapter->dev, "info: infra band=%d "  				"supported_rates_n\n", adapter->config_bands);  			k = mwifiex_copy_rates(rates, k, supported_rates_n,  |