Commit d310e405 authored by Eyal Shapira's avatar Eyal Shapira Committed by Johannes Berg

iwlwifi: mvm: support VHT in rs

Enable rs algorithm to use VHT rates and use 80Mhz.
This enables reaching VHT rates which wasn't possible.
Signed-off-by: default avatarEyal Shapira <eyal@wizery.com>
Reviewed-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 4515f30f
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
/* /*
* These serve as indexes into * These serve as indexes into
* struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT]; * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
* TODO: avoid overlap between legacy and HT rates
*/ */
enum { enum {
IWL_RATE_1M_INDEX = 0, IWL_RATE_1M_INDEX = 0,
...@@ -121,6 +122,7 @@ enum { ...@@ -121,6 +122,7 @@ enum {
IWL_RATE_2M_PLCP = 20, IWL_RATE_2M_PLCP = 20,
IWL_RATE_5M_PLCP = 55, IWL_RATE_5M_PLCP = 55,
IWL_RATE_11M_PLCP = 110, IWL_RATE_11M_PLCP = 110,
IWL_RATE_INVM_PLCP = -1,
}; };
/* /*
...@@ -177,6 +179,8 @@ enum { ...@@ -177,6 +179,8 @@ enum {
* which is the duplicate 20 MHz MCS (bit 5 set, all others zero.) * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)
*/ */
#define RATE_HT_MCS_RATE_CODE_MSK 0x7 #define RATE_HT_MCS_RATE_CODE_MSK 0x7
#define RATE_HT_MCS_NSS_POS 3
#define RATE_HT_MCS_NSS_MSK (3 << RATE_HT_MCS_NSS_POS)
/* Bit 10: (1) Use Green Field preamble */ /* Bit 10: (1) Use Green Field preamble */
#define RATE_HT_MCS_GF_POS 10 #define RATE_HT_MCS_GF_POS 10
......
...@@ -586,6 +586,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm); ...@@ -586,6 +586,9 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm);
/* Utils */ /* Utils */
int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags, int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
enum ieee80211_band band); enum ieee80211_band band);
void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
enum ieee80211_band band,
struct ieee80211_tx_rate *r);
u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
void iwl_mvm_dump_sram(struct iwl_mvm *mvm); void iwl_mvm_dump_sram(struct iwl_mvm *mvm);
......
This diff is collapsed.
...@@ -35,9 +35,11 @@ ...@@ -35,9 +35,11 @@
#include "iwl-trans.h" #include "iwl-trans.h"
struct iwl_rs_rate_info { struct iwl_rs_rate_info {
u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ u8 plcp_ht_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ u8 plcp_ht_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */
u8 plcp_vht_siso;
u8 plcp_vht_mimo2;
u8 prev_rs; /* previous rate used in rs algo */ u8 prev_rs; /* previous rate used in rs algo */
u8 next_rs; /* next rate used in rs algo */ u8 next_rs; /* next rate used in rs algo */
}; };
...@@ -83,35 +85,52 @@ enum { ...@@ -83,35 +85,52 @@ enum {
#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) #define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX)
/* uCode API values for OFDM high-throughput (HT) bit rates */ /* uCode API values for HT/VHT bit rates */
enum { enum {
IWL_RATE_SISO_6M_PLCP = 0, IWL_RATE_HT_SISO_MCS_0_PLCP = 0,
IWL_RATE_SISO_12M_PLCP = 1, IWL_RATE_HT_SISO_MCS_1_PLCP = 1,
IWL_RATE_SISO_18M_PLCP = 2, IWL_RATE_HT_SISO_MCS_2_PLCP = 2,
IWL_RATE_SISO_24M_PLCP = 3, IWL_RATE_HT_SISO_MCS_3_PLCP = 3,
IWL_RATE_SISO_36M_PLCP = 4, IWL_RATE_HT_SISO_MCS_4_PLCP = 4,
IWL_RATE_SISO_48M_PLCP = 5, IWL_RATE_HT_SISO_MCS_5_PLCP = 5,
IWL_RATE_SISO_54M_PLCP = 6, IWL_RATE_HT_SISO_MCS_6_PLCP = 6,
IWL_RATE_SISO_60M_PLCP = 7, IWL_RATE_HT_SISO_MCS_7_PLCP = 7,
IWL_RATE_MIMO2_6M_PLCP = 0x8, IWL_RATE_HT_MIMO2_MCS_0_PLCP = 0x8,
IWL_RATE_MIMO2_12M_PLCP = 0x9, IWL_RATE_HT_MIMO2_MCS_1_PLCP = 0x9,
IWL_RATE_MIMO2_18M_PLCP = 0xa, IWL_RATE_HT_MIMO2_MCS_2_PLCP = 0xA,
IWL_RATE_MIMO2_24M_PLCP = 0xb, IWL_RATE_HT_MIMO2_MCS_3_PLCP = 0xB,
IWL_RATE_MIMO2_36M_PLCP = 0xc, IWL_RATE_HT_MIMO2_MCS_4_PLCP = 0xC,
IWL_RATE_MIMO2_48M_PLCP = 0xd, IWL_RATE_HT_MIMO2_MCS_5_PLCP = 0xD,
IWL_RATE_MIMO2_54M_PLCP = 0xe, IWL_RATE_HT_MIMO2_MCS_6_PLCP = 0xE,
IWL_RATE_MIMO2_60M_PLCP = 0xf, IWL_RATE_HT_MIMO2_MCS_7_PLCP = 0xF,
IWL_RATE_MIMO3_6M_PLCP = 0x10, IWL_RATE_VHT_SISO_MCS_0_PLCP = 0,
IWL_RATE_MIMO3_12M_PLCP = 0x11, IWL_RATE_VHT_SISO_MCS_1_PLCP = 1,
IWL_RATE_MIMO3_18M_PLCP = 0x12, IWL_RATE_VHT_SISO_MCS_2_PLCP = 2,
IWL_RATE_MIMO3_24M_PLCP = 0x13, IWL_RATE_VHT_SISO_MCS_3_PLCP = 3,
IWL_RATE_MIMO3_36M_PLCP = 0x14, IWL_RATE_VHT_SISO_MCS_4_PLCP = 4,
IWL_RATE_MIMO3_48M_PLCP = 0x15, IWL_RATE_VHT_SISO_MCS_5_PLCP = 5,
IWL_RATE_MIMO3_54M_PLCP = 0x16, IWL_RATE_VHT_SISO_MCS_6_PLCP = 6,
IWL_RATE_MIMO3_60M_PLCP = 0x17, IWL_RATE_VHT_SISO_MCS_7_PLCP = 7,
IWL_RATE_SISO_INVM_PLCP, IWL_RATE_VHT_SISO_MCS_8_PLCP = 8,
IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, IWL_RATE_VHT_SISO_MCS_9_PLCP = 9,
IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, IWL_RATE_VHT_MIMO2_MCS_0_PLCP = 0x10,
IWL_RATE_VHT_MIMO2_MCS_1_PLCP = 0x11,
IWL_RATE_VHT_MIMO2_MCS_2_PLCP = 0x12,
IWL_RATE_VHT_MIMO2_MCS_3_PLCP = 0x13,
IWL_RATE_VHT_MIMO2_MCS_4_PLCP = 0x14,
IWL_RATE_VHT_MIMO2_MCS_5_PLCP = 0x15,
IWL_RATE_VHT_MIMO2_MCS_6_PLCP = 0x16,
IWL_RATE_VHT_MIMO2_MCS_7_PLCP = 0x17,
IWL_RATE_VHT_MIMO2_MCS_8_PLCP = 0x18,
IWL_RATE_VHT_MIMO2_MCS_9_PLCP = 0x19,
IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_VHT_SISO_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_VHT_MIMO2_MCS_INV_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_SISO_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_SISO_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_MIMO2_MCS_8_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
IWL_RATE_HT_MIMO2_MCS_9_PLCP = IWL_RATE_HT_SISO_MCS_INV_PLCP,
}; };
#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
...@@ -196,20 +215,31 @@ enum { ...@@ -196,20 +215,31 @@ enum {
enum iwl_table_type { enum iwl_table_type {
LQ_NONE, LQ_NONE,
LQ_G, /* legacy types */ LQ_LEGACY_G, /* legacy types */
LQ_A, LQ_LEGACY_A,
LQ_SISO, /* high-throughput types */ LQ_HT_SISO, /* HT types */
LQ_MIMO2, LQ_HT_MIMO2,
LQ_VHT_SISO, /* VHT types */
LQ_VHT_MIMO2,
LQ_MAX, LQ_MAX,
}; };
#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) #define is_legacy(tbl) (((tbl) == LQ_LEGACY_G) || ((tbl) == LQ_LEGACY_A))
#define is_siso(tbl) ((tbl) == LQ_SISO) #define is_ht_siso(tbl) ((tbl) == LQ_HT_SISO)
#define is_mimo2(tbl) ((tbl) == LQ_MIMO2) #define is_ht_mimo2(tbl) ((tbl) == LQ_HT_MIMO2)
#define is_mimo(tbl) is_mimo2(tbl) #define is_vht_siso(tbl) ((tbl) == LQ_VHT_SISO)
#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) #define is_vht_mimo2(tbl) ((tbl) == LQ_VHT_MIMO2)
#define is_a_band(tbl) ((tbl) == LQ_A) #define is_siso(tbl) (is_ht_siso(tbl) || is_vht_siso(tbl))
#define is_g_and(tbl) ((tbl) == LQ_G) #define is_mimo2(tbl) (is_ht_mimo2(tbl) || is_vht_mimo2(tbl))
#define is_mimo(tbl) (is_mimo2(tbl))
#define is_ht(tbl) (is_ht_siso(tbl) || is_ht_mimo2(tbl))
#define is_vht(tbl) (is_vht_siso(tbl) || is_vht_mimo2(tbl))
#define is_a_band(tbl) ((tbl) == LQ_LEGACY_A)
#define is_g_band(tbl) ((tbl) == LQ_LEGACY_G)
#define is_ht20(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_20)
#define is_ht40(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_40)
#define is_ht80(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_80)
#define IWL_MAX_MCS_DISPLAY_SIZE 12 #define IWL_MAX_MCS_DISPLAY_SIZE 12
...@@ -240,7 +270,7 @@ struct iwl_scale_tbl_info { ...@@ -240,7 +270,7 @@ struct iwl_scale_tbl_info {
enum iwl_table_type lq_type; enum iwl_table_type lq_type;
u8 ant_type; u8 ant_type;
u8 is_SGI; /* 1 = short guard interval */ u8 is_SGI; /* 1 = short guard interval */
u8 is_ht40; /* 1 = 40 MHz channel width */ u32 bw; /* channel bandwidth; RATE_MCS_CHAN_WIDTH_XX */
u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
u8 max_search; /* maximun number of tables we can search */ u8 max_search; /* maximun number of tables we can search */
s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */
...@@ -271,6 +301,7 @@ struct iwl_lq_sta { ...@@ -271,6 +301,7 @@ struct iwl_lq_sta {
u8 action_counter; /* # mode-switch actions tried */ u8 action_counter; /* # mode-switch actions tried */
u8 is_green; u8 is_green;
bool is_vht;
enum ieee80211_band band; enum ieee80211_band band;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
......
...@@ -511,16 +511,10 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status) ...@@ -511,16 +511,10 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status)
} }
#endif /* CONFIG_IWLWIFI_DEBUG */ #endif /* CONFIG_IWLWIFI_DEBUG */
/** void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
* translate ucode response to mac80211 tx status control values enum ieee80211_band band,
*/ struct ieee80211_tx_rate *r)
static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags,
struct ieee80211_tx_info *info)
{ {
struct ieee80211_tx_rate *r = &info->status.rates[0];
info->status.antenna =
((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
if (rate_n_flags & RATE_HT_MCS_GF_MSK) if (rate_n_flags & RATE_HT_MCS_GF_MSK)
r->flags |= IEEE80211_TX_RC_GREEN_FIELD; r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) { switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
...@@ -549,10 +543,23 @@ static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags, ...@@ -549,10 +543,23 @@ static void iwl_mvm_hwrate_to_tx_control(u32 rate_n_flags,
r->flags |= IEEE80211_TX_RC_VHT_MCS; r->flags |= IEEE80211_TX_RC_VHT_MCS;
} else { } else {
r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, r->idx = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
info->band); band);
} }
} }
/**
* translate ucode response to mac80211 tx status control values
*/
static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags,
struct ieee80211_tx_info *info)
{
struct ieee80211_tx_rate *r = &info->status.rates[0];
info->status.antenna =
((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r);
}
static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt) struct iwl_rx_packet *pkt)
{ {
...@@ -602,8 +609,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, ...@@ -602,8 +609,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
} }
info->status.rates[0].count = tx_resp->failure_frame + 1; info->status.rates[0].count = tx_resp->failure_frame + 1;
iwl_mvm_hwrate_to_tx_control(le32_to_cpu(tx_resp->initial_rate), iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate),
info); info);
/* Single frame failure in an AMPDU queue => send BAR */ /* Single frame failure in an AMPDU queue => send BAR */
if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE && if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE &&
...@@ -900,8 +907,8 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, ...@@ -900,8 +907,8 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
info->flags |= IEEE80211_TX_STAT_AMPDU; info->flags |= IEEE80211_TX_STAT_AMPDU;
info->status.ampdu_ack_len = ba_notif->txed_2_done; info->status.ampdu_ack_len = ba_notif->txed_2_done;
info->status.ampdu_len = ba_notif->txed; info->status.ampdu_len = ba_notif->txed;
iwl_mvm_hwrate_to_tx_control(tid_data->rate_n_flags, iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags,
info); info);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment