Skip to content

Commit

Permalink
iwlwifi: mvm: Support version 3 of tlc_update_notif.
Browse files Browse the repository at this point in the history
As part of the new rate_n_flags, a new version of tlc_update_notif
was added in FW in order to support the new rate_n_flags.
Add support for the new version, and move the all API to use the
new rate_n_flags only (if FW supports the old one - convert it).

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20211017123741.9fc0cb5d5898.I1f88e02317f79f1be7f792c01236d836045a44b3@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
  • Loading branch information
Miri Korenblit authored and Luca Coelho committed Oct 22, 2021
1 parent 9998f81 commit 82cdbd1
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 144 deletions.
16 changes: 16 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ struct iwl_tlc_update_notif {
__le32 amsdu_enabled;
} __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */


#define IWL_MAX_MCS_DISPLAY_SIZE 12

struct iwl_rate_mcs_info {
char mbps[IWL_MAX_MCS_DISPLAY_SIZE];
char mcs[IWL_MAX_MCS_DISPLAY_SIZE];
};

/*
* These serve as indexes into
* struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
Expand Down Expand Up @@ -226,6 +234,8 @@ enum {
IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX,
IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,
IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1,
IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
IWL_RATE_INVALID = IWL_RATE_COUNT,
};

#define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)
Expand Down Expand Up @@ -548,6 +558,7 @@ enum {
#define RATE_MCS_SGI_POS RATE_MCS_HE_GI_LTF_POS
#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS)
#define RATE_MCS_HE_SU_4_LTF 3
#define RATE_MCS_HE_SU_4_LTF_08_GI 4

/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */
#define RATE_MCS_HE_TYPE_POS 23
Expand Down Expand Up @@ -700,5 +711,10 @@ struct iwl_lq_cmd {
u8 iwl_fw_rate_idx_to_plcp(int idx);
u32 iwl_new_rate_from_v1(u32 rate_v1);
u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags);
const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx);
const char *iwl_rs_pretty_ant(u8 ant);
const char *iwl_rs_pretty_bw(int bw);
int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
bool iwl_he_is_sgi(u32 rate_n_flags);

#endif /* __iwl_fw_api_rs_h__ */
125 changes: 123 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/fw/rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
#include <net/mac80211.h>
#include "fw/api/rs.h"
#include "iwl-drv.h"
#include "iwl-config.h"

#define IWL_DECLARE_RATE_INFO(r) \
[IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP

u8 iwl_fw_rate_idx_to_plcp(int idx)
{
/*
* Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP
* */
Expand All @@ -30,10 +29,68 @@ static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(54),
};

/* mbps, mcs */
static const struct iwl_rate_mcs_info rate_mcs[IWL_RATE_COUNT] = {
{ "1", "BPSK DSSS"},
{ "2", "QPSK DSSS"},
{"5.5", "BPSK CCK"},
{ "11", "QPSK CCK"},
{ "6", "BPSK 1/2"},
{ "9", "BPSK 1/2"},
{ "12", "QPSK 1/2"},
{ "18", "QPSK 3/4"},
{ "24", "16QAM 1/2"},
{ "36", "16QAM 3/4"},
{ "48", "64QAM 2/3"},
{ "54", "64QAM 3/4"},
{ "60", "64QAM 5/6"},
};

static const char * const ant_name[] = {
[ANT_NONE] = "None",
[ANT_A] = "A",
[ANT_B] = "B",
[ANT_AB] = "AB",
};

static const char * const pretty_bw[] = {
"20Mhz",
"40Mhz",
"80Mhz",
"160 Mhz",
"320Mhz",
};

u8 iwl_fw_rate_idx_to_plcp(int idx)
{
return fw_rate_idx_to_plcp[idx];
}
IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp);

const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx)
{
return &rate_mcs[idx];
}
IWL_EXPORT_SYMBOL(iwl_rate_mcs);

const char *iwl_rs_pretty_ant(u8 ant)
{
if (ant >= ARRAY_SIZE(ant_name))
return "UNKNOWN";

return ant_name[ant];
}
IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant);

const char *iwl_rs_pretty_bw(int bw)
{
if (bw >= ARRAY_SIZE(pretty_bw))
return "unknown bw";

return pretty_bw[bw];
}
IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);

u32 iwl_new_rate_from_v1(u32 rate_v1)
{
u32 rate_v2 = 0;
Expand Down Expand Up @@ -129,3 +186,67 @@ u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)
return -1;
}

int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
{
char *type;
u8 mcs = 0, nss = 0;
u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>
RATE_MCS_CHAN_WIDTH_POS;
u32 format = rate & RATE_MCS_MOD_TYPE_MSK;
bool sgi;

if (format == RATE_MCS_CCK_MSK ||
format == RATE_MCS_LEGACY_OFDM_MSK) {
int legacy_rate = rate & RATE_LEGACY_RATE_MSK;
int index = format == RATE_MCS_CCK_MSK ?
legacy_rate :
legacy_rate + IWL_FIRST_OFDM_RATE;

return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
iwl_rs_pretty_ant(ant),
index == IWL_RATE_INVALID ? "BAD" :
iwl_rate_mcs(index)->mbps);
}

if (format == RATE_MCS_VHT_MSK)
type = "VHT";
else if (format == RATE_MCS_HT_MSK)
type = "HT";
else if (format == RATE_MCS_HE_MSK)
type = "HE";
else
type = "Unknown"; /* shouldn't happen */

mcs = format == RATE_MCS_HT_MSK ?
RATE_HT_MCS_INDEX(rate) :
rate & RATE_MCS_CODE_MSK;
nss = ((rate & RATE_MCS_NSS_MSK)
>> RATE_MCS_NSS_POS) + 1;
sgi = format == RATE_MCS_HE_MSK ?
iwl_he_is_sgi(rate) :
rate & RATE_MCS_SGI_MSK;

return scnprintf(buf, bufsz,
"0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",
rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,
(sgi) ? "SGI " : "NGI ",
(rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
(rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
(rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",
(rate & RATE_MCS_BF_MSK) ? "BF " : "");
}
IWL_EXPORT_SYMBOL(rs_pretty_print_rate);

bool iwl_he_is_sgi(u32 rate_n_flags)
{
u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK;

if (type == RATE_MCS_HE_TYPE_SU ||
type == RATE_MCS_HE_TYPE_EXT_SU)
return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI;
return false;
}
IWL_EXPORT_SYMBOL(iwl_he_is_sgi);

4 changes: 2 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,8 +985,8 @@ static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
continue;
pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
(int)(ARRAY_SIZE(stats->last_rates) - i));
pos += rs_pretty_print_rate(pos, endpos - pos,
stats->last_rates[idx]);
pos += rs_pretty_print_rate_v1(pos, endpos - pos,
stats->last_rates[idx]);
if (pos < endpos - 1)
*pos++ = '\n';
}
Expand Down
150 changes: 80 additions & 70 deletions drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -4878,7 +4878,9 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,

static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
{
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) {
u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;

switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
case RATE_MCS_CHAN_WIDTH_20:
rinfo->bw = RATE_INFO_BW_20;
break;
Expand All @@ -4893,57 +4895,92 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
break;
}

if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
rinfo->flags |= RATE_INFO_FLAGS_MCS;
rinfo->mcs = u32_get_bits(rate_n_flags, RATE_HT_MCS_INDEX_MSK_V1);
rinfo->nss = u32_get_bits(rate_n_flags,
RATE_HT_MCS_NSS_MSK_V1) + 1;
if (rate_n_flags & RATE_MCS_SGI_MSK_V1)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
} else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {
rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
rinfo->mcs = u32_get_bits(rate_n_flags,
RATE_VHT_MCS_RATE_CODE_MSK);
rinfo->nss = u32_get_bits(rate_n_flags,
RATE_VHT_MCS_NSS_MSK) + 1;
if (rate_n_flags & RATE_MCS_SGI_MSK_V1)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
} else if (rate_n_flags & RATE_MCS_HE_MSK_V1) {
if (format == RATE_MCS_CCK_MSK ||
format == RATE_MCS_LEGACY_OFDM_MSK) {
int rate = u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK);

/* add the offset needed to get to the legacy ofdm indices */
if (format == RATE_MCS_LEGACY_OFDM_MSK)
rate += IWL_FIRST_OFDM_RATE;

switch (rate) {
case IWL_RATE_1M_INDEX:
rinfo->legacy = 10;
break;
case IWL_RATE_2M_INDEX:
rinfo->legacy = 20;
break;
case IWL_RATE_5M_INDEX:
rinfo->legacy = 55;
break;
case IWL_RATE_11M_INDEX:
rinfo->legacy = 110;
break;
case IWL_RATE_6M_INDEX:
rinfo->legacy = 60;
break;
case IWL_RATE_9M_INDEX:
rinfo->legacy = 90;
break;
case IWL_RATE_12M_INDEX:
rinfo->legacy = 120;
break;
case IWL_RATE_18M_INDEX:
rinfo->legacy = 180;
break;
case IWL_RATE_24M_INDEX:
rinfo->legacy = 240;
break;
case IWL_RATE_36M_INDEX:
rinfo->legacy = 360;
break;
case IWL_RATE_48M_INDEX:
rinfo->legacy = 480;
break;
case IWL_RATE_54M_INDEX:
rinfo->legacy = 540;
}
return;
}

rinfo->nss = u32_get_bits(rate_n_flags,
RATE_MCS_NSS_MSK) + 1;
rinfo->mcs = format == RATE_MCS_HT_MSK ?
RATE_HT_MCS_INDEX(rate_n_flags) :
u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK);

if (format == RATE_MCS_HE_MSK) {
u32 gi_ltf = u32_get_bits(rate_n_flags,
RATE_MCS_HE_GI_LTF_MSK_V1);
RATE_MCS_HE_GI_LTF_MSK);

rinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
rinfo->mcs = u32_get_bits(rate_n_flags,
RATE_VHT_MCS_RATE_CODE_MSK);
rinfo->nss = u32_get_bits(rate_n_flags,
RATE_VHT_MCS_NSS_MSK) + 1;

if (rate_n_flags & RATE_MCS_HE_106T_MSK_V1) {
if (rate_n_flags & RATE_MCS_HE_106T_MSK) {
rinfo->bw = RATE_INFO_BW_HE_RU;
rinfo->he_ru_alloc = NL80211_RATE_INFO_HE_RU_ALLOC_106;
}

switch (rate_n_flags & RATE_MCS_HE_TYPE_MSK_V1) {
case RATE_MCS_HE_TYPE_SU_V1:
case RATE_MCS_HE_TYPE_EXT_SU_V1:
switch (rate_n_flags & RATE_MCS_HE_TYPE_MSK) {
case RATE_MCS_HE_TYPE_SU:
case RATE_MCS_HE_TYPE_EXT_SU:
if (gi_ltf == 0 || gi_ltf == 1)
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
else if (gi_ltf == 2)
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
else if (rate_n_flags & RATE_MCS_SGI_MSK_V1)
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
else
else if (gi_ltf == 3)
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
else
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
break;
case RATE_MCS_HE_TYPE_MU_V1:
case RATE_MCS_HE_TYPE_MU:
if (gi_ltf == 0 || gi_ltf == 1)
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
else if (gi_ltf == 2)
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
else
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
break;
case RATE_MCS_HE_TYPE_TRIG_V1:
case RATE_MCS_HE_TYPE_TRIG:
if (gi_ltf == 0 || gi_ltf == 1)
rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
else
Expand All @@ -4953,46 +4990,19 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)

if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK)
rinfo->he_dcm = 1;
} else {
switch (u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK_V1)) {
case IWL_RATE_1M_PLCP:
rinfo->legacy = 10;
break;
case IWL_RATE_2M_PLCP:
rinfo->legacy = 20;
break;
case IWL_RATE_5M_PLCP:
rinfo->legacy = 55;
break;
case IWL_RATE_11M_PLCP:
rinfo->legacy = 110;
break;
case IWL_RATE_6M_PLCP:
rinfo->legacy = 60;
break;
case IWL_RATE_9M_PLCP:
rinfo->legacy = 90;
break;
case IWL_RATE_12M_PLCP:
rinfo->legacy = 120;
break;
case IWL_RATE_18M_PLCP:
rinfo->legacy = 180;
break;
case IWL_RATE_24M_PLCP:
rinfo->legacy = 240;
break;
case IWL_RATE_36M_PLCP:
rinfo->legacy = 360;
break;
case IWL_RATE_48M_PLCP:
rinfo->legacy = 480;
break;
case IWL_RATE_54M_PLCP:
rinfo->legacy = 540;
break;
}
return;
}

if (rate_n_flags & RATE_MCS_SGI_MSK)
rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;

if (format == RATE_MCS_HT_MSK) {
rinfo->flags |= RATE_INFO_FLAGS_MCS;

} else if (format == RATE_MCS_VHT_MSK) {
rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
}

}

static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
Expand Down
Loading

0 comments on commit 82cdbd1

Please sign in to comment.