brintos

brintos / linux-shallow public Read only

0
0
Text · 6.5 KiB · 8f99e50 Raw
257 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause2/*3 * Copyright (C) 2021-2022 Intel Corporation4 */5 6#include <net/mac80211.h>7#include "fw/api/rs.h"8#include "iwl-drv.h"9#include "iwl-config.h"10 11#define IWL_DECLARE_RATE_INFO(r) \12	[IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP13 14/*15 * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP16 * */17static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = {18	IWL_DECLARE_RATE_INFO(1),19	IWL_DECLARE_RATE_INFO(2),20	IWL_DECLARE_RATE_INFO(5),21	IWL_DECLARE_RATE_INFO(11),22	IWL_DECLARE_RATE_INFO(6),23	IWL_DECLARE_RATE_INFO(9),24	IWL_DECLARE_RATE_INFO(12),25	IWL_DECLARE_RATE_INFO(18),26	IWL_DECLARE_RATE_INFO(24),27	IWL_DECLARE_RATE_INFO(36),28	IWL_DECLARE_RATE_INFO(48),29	IWL_DECLARE_RATE_INFO(54),30};31 32/* mbps, mcs */33static const struct iwl_rate_mcs_info rate_mcs[IWL_RATE_COUNT] = {34	{  "1", "BPSK DSSS"},35	{  "2", "QPSK DSSS"},36	{"5.5", "BPSK CCK"},37	{ "11", "QPSK CCK"},38	{  "6", "BPSK 1/2"},39	{  "9", "BPSK 1/2"},40	{ "12", "QPSK 1/2"},41	{ "18", "QPSK 3/4"},42	{ "24", "16QAM 1/2"},43	{ "36", "16QAM 3/4"},44	{ "48", "64QAM 2/3"},45	{ "54", "64QAM 3/4"},46	{ "60", "64QAM 5/6"},47};48 49static const char * const ant_name[] = {50	[ANT_NONE] = "None",51	[ANT_A]    = "A",52	[ANT_B]    = "B",53	[ANT_AB]   = "AB",54};55 56static const char * const pretty_bw[] = {57	"20Mhz",58	"40Mhz",59	"80Mhz",60	"160 Mhz",61	"320Mhz",62};63 64u8 iwl_fw_rate_idx_to_plcp(int idx)65{66	return fw_rate_idx_to_plcp[idx];67}68IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp);69 70const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx)71{72	return &rate_mcs[idx];73}74IWL_EXPORT_SYMBOL(iwl_rate_mcs);75 76const char *iwl_rs_pretty_ant(u8 ant)77{78	if (ant >= ARRAY_SIZE(ant_name))79		return "UNKNOWN";80 81	return ant_name[ant];82}83IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant);84 85const char *iwl_rs_pretty_bw(int bw)86{87	if (bw >= ARRAY_SIZE(pretty_bw))88		return "unknown bw";89 90	return pretty_bw[bw];91}92IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);93 94static u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)95{96	int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;97	int idx;98	bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1);99	int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0;100	int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE;101 102	for (idx = offset; idx < last; idx++)103		if (iwl_fw_rate_idx_to_plcp(idx) == rate)104			return idx - offset;105	return IWL_RATE_INVALID;106}107 108u32 iwl_new_rate_from_v1(u32 rate_v1)109{110	u32 rate_v2 = 0;111	u32 dup = 0;112 113	if (rate_v1 == 0)114		return rate_v1;115	/* convert rate */116	if (rate_v1 & RATE_MCS_HT_MSK_V1) {117		u32 nss = 0;118 119		rate_v2 |= RATE_MCS_HT_MSK;120		rate_v2 |=121			rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1;122		nss = (rate_v1 & RATE_HT_MCS_MIMO2_MSK) >>123			RATE_HT_MCS_NSS_POS_V1;124		rate_v2 |= nss << RATE_MCS_NSS_POS;125	} else if (rate_v1 & RATE_MCS_VHT_MSK_V1 ||126		   rate_v1 & RATE_MCS_HE_MSK_V1) {127		rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;128 129		rate_v2 |= rate_v1 & RATE_MCS_NSS_MSK;130 131		if (rate_v1 & RATE_MCS_HE_MSK_V1) {132			u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;133			u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1;134			u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >>135				RATE_MCS_HE_106T_POS_V1;136			u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >>137				RATE_MCS_HE_GI_LTF_POS;138 139			if ((he_type_bits == RATE_MCS_HE_TYPE_SU ||140			     he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) &&141			    he_gi_ltf == RATE_MCS_HE_SU_4_LTF)142				/* the new rate have an additional bit to143				 * represent the value 4 rather then using SGI144				 * bit for this purpose - as it was done in the old145				 * rate */146				he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >>147					RATE_MCS_SGI_POS_V1;148 149			rate_v2 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS;150			rate_v2 |= he_type << RATE_MCS_HE_TYPE_POS;151			rate_v2 |= he_106t << RATE_MCS_HE_106T_POS;152			rate_v2 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK;153			rate_v2 |= RATE_MCS_HE_MSK;154		} else {155			rate_v2 |= RATE_MCS_VHT_MSK;156		}157	/* if legacy format */158	} else {159		u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1);160 161		if (WARN_ON_ONCE(legacy_rate == IWL_RATE_INVALID))162			legacy_rate = (rate_v1 & RATE_MCS_CCK_MSK_V1) ?163				IWL_FIRST_CCK_RATE : IWL_FIRST_OFDM_RATE;164 165		rate_v2 |= legacy_rate;166		if (!(rate_v1 & RATE_MCS_CCK_MSK_V1))167			rate_v2 |= RATE_MCS_LEGACY_OFDM_MSK;168	}169 170	/* convert flags */171	if (rate_v1 & RATE_MCS_LDPC_MSK_V1)172		rate_v2 |= RATE_MCS_LDPC_MSK;173	rate_v2 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) |174		(rate_v1 & RATE_MCS_ANT_AB_MSK) |175		(rate_v1 & RATE_MCS_STBC_MSK) |176		(rate_v1 & RATE_MCS_BF_MSK);177 178	dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1;179	if (dup) {180		rate_v2 |= RATE_MCS_DUP_MSK;181		rate_v2 |= dup << RATE_MCS_CHAN_WIDTH_POS;182	}183 184	if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) &&185	    (rate_v1 & RATE_MCS_SGI_MSK_V1))186		rate_v2 |= RATE_MCS_SGI_MSK;187 188	return rate_v2;189}190IWL_EXPORT_SYMBOL(iwl_new_rate_from_v1);191 192int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)193{194	char *type;195	u8 mcs = 0, nss = 0;196	u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;197	u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>198		RATE_MCS_CHAN_WIDTH_POS;199	u32 format = rate & RATE_MCS_MOD_TYPE_MSK;200	bool sgi;201 202	if (format == RATE_MCS_CCK_MSK ||203	    format == RATE_MCS_LEGACY_OFDM_MSK) {204		int legacy_rate = rate & RATE_LEGACY_RATE_MSK;205		int index = format == RATE_MCS_CCK_MSK ?206			legacy_rate :207			legacy_rate + IWL_FIRST_OFDM_RATE;208 209		return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",210				 iwl_rs_pretty_ant(ant),211				 iwl_rate_mcs(index)->mbps);212	}213 214	if (format ==  RATE_MCS_VHT_MSK)215		type = "VHT";216	else if (format ==  RATE_MCS_HT_MSK)217		type = "HT";218	else if (format == RATE_MCS_HE_MSK)219		type = "HE";220	else if (format == RATE_MCS_EHT_MSK)221		type = "EHT";222	else223		type = "Unknown"; /* shouldn't happen */224 225	mcs = format == RATE_MCS_HT_MSK ?226		RATE_HT_MCS_INDEX(rate) :227		rate & RATE_MCS_CODE_MSK;228	nss = ((rate & RATE_MCS_NSS_MSK)229	       >> RATE_MCS_NSS_POS) + 1;230	sgi = format == RATE_MCS_HE_MSK ?231		iwl_he_is_sgi(rate) :232		rate & RATE_MCS_SGI_MSK;233 234	return scnprintf(buf, bufsz,235			 "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",236			 rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,237			 (sgi) ? "SGI " : "NGI ",238			 (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",239			 (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",240			 (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",241			 (rate & RATE_MCS_BF_MSK) ? "BF " : "");242}243IWL_EXPORT_SYMBOL(rs_pretty_print_rate);244 245bool iwl_he_is_sgi(u32 rate_n_flags)246{247	u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;248	u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK;249 250	if (type == RATE_MCS_HE_TYPE_SU ||251	    type == RATE_MCS_HE_TYPE_EXT_SU)252		return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI;253	return false;254}255IWL_EXPORT_SYMBOL(iwl_he_is_sgi);256 257