cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rs.c (6679B)


      1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
      2/*
      3 * Copyright (C) 2021 Intel Corporation
      4 */
      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_PLCP
     13
     14/*
     15 * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP
     16 * */
     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_VHT_MCS_MIMO2_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 to
    143				 * represent the value 4 rather then using SGI
    144				 * bit for this purpose - as it was done in the old
    145				 * 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				 index == IWL_RATE_INVALID ? "BAD" :
    212				 iwl_rate_mcs(index)->mbps);
    213	}
    214
    215	if (format ==  RATE_MCS_VHT_MSK)
    216		type = "VHT";
    217	else if (format ==  RATE_MCS_HT_MSK)
    218		type = "HT";
    219	else if (format == RATE_MCS_HE_MSK)
    220		type = "HE";
    221	else
    222		type = "Unknown"; /* shouldn't happen */
    223
    224	mcs = format == RATE_MCS_HT_MSK ?
    225		RATE_HT_MCS_INDEX(rate) :
    226		rate & RATE_MCS_CODE_MSK;
    227	nss = ((rate & RATE_MCS_NSS_MSK)
    228	       >> RATE_MCS_NSS_POS) + 1;
    229	sgi = format == RATE_MCS_HE_MSK ?
    230		iwl_he_is_sgi(rate) :
    231		rate & RATE_MCS_SGI_MSK;
    232
    233	return scnprintf(buf, bufsz,
    234			 "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",
    235			 rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,
    236			 (sgi) ? "SGI " : "NGI ",
    237			 (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
    238			 (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
    239			 (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",
    240			 (rate & RATE_MCS_BF_MSK) ? "BF " : "");
    241}
    242IWL_EXPORT_SYMBOL(rs_pretty_print_rate);
    243
    244bool iwl_he_is_sgi(u32 rate_n_flags)
    245{
    246	u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
    247	u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK;
    248
    249	if (type == RATE_MCS_HE_TYPE_SU ||
    250	    type == RATE_MCS_HE_TYPE_EXT_SU)
    251		return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI;
    252	return false;
    253}
    254IWL_EXPORT_SYMBOL(iwl_he_is_sgi);
    255