summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi/fw/rs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/fw/rs.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/rs.c125
1 files changed, 123 insertions, 2 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/rs.c b/drivers/net/wireless/intel/iwlwifi/fw/rs.c
index 4e066588d5ba..a21c3befd93b 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/rs.c
@@ -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
* */
@@ -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;
@@ -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);
+