diff options
author | Eyal Shapira <eyal@wizery.com> | 2015-01-29 18:38:29 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2015-03-01 09:55:03 -0500 |
commit | ba69d0e36261234efa315ff34ef6f59da9f98ac3 (patch) | |
tree | 65657e6d88668e2ca12752f01b8503098bd6cf79 /drivers/net/wireless/iwlwifi/mvm/rs.c | |
parent | 0b8d17f30304bedff77d47450839865048b1b626 (diff) |
iwlwifi: mvm: rs: adapt rate matching to new STBC/BFER
Once the FW supports autonomous decision between STBC/BFER/SISO
we no longer set the STBC bit and ANT_AB in the rate table.
However the FW rate in the tx response will have the STBC
or BFER bit set and the antennas set to ANT_AB in case these
were chosen by it. This will cause us to discard any such
response as unmatching the current LQ table and thus break
the rs search cycle completely.
Fix this by relaxing the rate matching in case we're working
with the new API and STBC/BFER are used.
Signed-off-by: Eyal Shapira <eyalx.shapira@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/rs.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/rs.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 2e45b81dd0a3..37002cfbe872 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -807,6 +807,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
807 | rate->ldpc = true; | 807 | rate->ldpc = true; |
808 | if (ucode_rate & RATE_MCS_VHT_STBC_MSK) | 808 | if (ucode_rate & RATE_MCS_VHT_STBC_MSK) |
809 | rate->stbc = true; | 809 | rate->stbc = true; |
810 | if (ucode_rate & RATE_MCS_BF_MSK) | ||
811 | rate->bfer = true; | ||
810 | 812 | ||
811 | rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; | 813 | rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; |
812 | 814 | ||
@@ -816,7 +818,9 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
816 | 818 | ||
817 | if (nss == 1) { | 819 | if (nss == 1) { |
818 | rate->type = LQ_HT_SISO; | 820 | rate->type = LQ_HT_SISO; |
819 | WARN_ON_ONCE(!rate->stbc && num_of_ant != 1); | 821 | WARN_ONCE(!rate->stbc && !rate->bfer && num_of_ant != 1, |
822 | "stbc %d bfer %d", | ||
823 | rate->stbc, rate->bfer); | ||
820 | } else if (nss == 2) { | 824 | } else if (nss == 2) { |
821 | rate->type = LQ_HT_MIMO2; | 825 | rate->type = LQ_HT_MIMO2; |
822 | WARN_ON_ONCE(num_of_ant != 2); | 826 | WARN_ON_ONCE(num_of_ant != 2); |
@@ -829,7 +833,9 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
829 | 833 | ||
830 | if (nss == 1) { | 834 | if (nss == 1) { |
831 | rate->type = LQ_VHT_SISO; | 835 | rate->type = LQ_VHT_SISO; |
832 | WARN_ON_ONCE(!rate->stbc && num_of_ant != 1); | 836 | WARN_ONCE(!rate->stbc && !rate->bfer && num_of_ant != 1, |
837 | "stbc %d bfer %d", | ||
838 | rate->stbc, rate->bfer); | ||
833 | } else if (nss == 2) { | 839 | } else if (nss == 2) { |
834 | rate->type = LQ_VHT_MIMO2; | 840 | rate->type = LQ_VHT_MIMO2; |
835 | WARN_ON_ONCE(num_of_ant != 2); | 841 | WARN_ON_ONCE(num_of_ant != 2); |
@@ -1008,13 +1014,32 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, | |||
1008 | rs_get_lower_rate_in_column(lq_sta, rate); | 1014 | rs_get_lower_rate_in_column(lq_sta, rate); |
1009 | } | 1015 | } |
1010 | 1016 | ||
1011 | /* Check if both rates are identical */ | 1017 | /* Check if both rates are identical |
1018 | * allow_ant_mismatch enables matching a SISO rate on ANT_A or ANT_B | ||
1019 | * with a rate indicating STBC/BFER and ANT_AB. | ||
1020 | */ | ||
1012 | static inline bool rs_rate_equal(struct rs_rate *a, | 1021 | static inline bool rs_rate_equal(struct rs_rate *a, |
1013 | struct rs_rate *b) | 1022 | struct rs_rate *b, |
1014 | { | 1023 | bool allow_ant_mismatch) |
1024 | |||
1025 | { | ||
1026 | bool ant_match = (a->ant == b->ant) && (a->stbc == b->stbc) && | ||
1027 | (a->bfer == b->bfer); | ||
1028 | |||
1029 | if (allow_ant_mismatch) { | ||
1030 | if (a->stbc || a->bfer) { | ||
1031 | WARN_ONCE(a->ant != ANT_AB, "stbc %d bfer %d ant %d", | ||
1032 | a->stbc, a->bfer, a->ant); | ||
1033 | ant_match |= (b->ant == ANT_A || b->ant == ANT_B); | ||
1034 | } else if (b->stbc || b->bfer) { | ||
1035 | WARN_ONCE(b->ant != ANT_AB, "stbc %d bfer %d ant %d", | ||
1036 | b->stbc, b->bfer, b->ant); | ||
1037 | ant_match |= (a->ant == ANT_A || a->ant == ANT_B); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1015 | return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) && | 1041 | return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) && |
1016 | (a->ldpc == b->ldpc) && (a->index == b->index) && | 1042 | (a->ldpc == b->ldpc) && (a->index == b->index) && ant_match; |
1017 | (a->ant == b->ant); | ||
1018 | } | 1043 | } |
1019 | 1044 | ||
1020 | /* Check if both rates share the same column */ | 1045 | /* Check if both rates share the same column */ |
@@ -1023,7 +1048,7 @@ static inline bool rs_rate_column_match(struct rs_rate *a, | |||
1023 | { | 1048 | { |
1024 | bool ant_match; | 1049 | bool ant_match; |
1025 | 1050 | ||
1026 | if (a->stbc) | 1051 | if (a->stbc || a->bfer) |
1027 | ant_match = (b->ant == ANT_A || b->ant == ANT_B); | 1052 | ant_match = (b->ant == ANT_A || b->ant == ANT_B); |
1028 | else | 1053 | else |
1029 | ant_match = (a->ant == b->ant); | 1054 | ant_match = (a->ant == b->ant); |
@@ -1061,6 +1086,8 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1061 | u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1]; | 1086 | u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1]; |
1062 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 1087 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
1063 | struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta; | 1088 | struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta; |
1089 | bool allow_ant_mismatch = mvm->fw->ucode_capa.api[0] & | ||
1090 | IWL_UCODE_TLV_API_LQ_SS_PARAMS; | ||
1064 | 1091 | ||
1065 | /* Treat uninitialized rate scaling data same as non-existing. */ | 1092 | /* Treat uninitialized rate scaling data same as non-existing. */ |
1066 | if (!lq_sta) { | 1093 | if (!lq_sta) { |
@@ -1110,7 +1137,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1110 | rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); | 1137 | rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate); |
1111 | 1138 | ||
1112 | /* Here we actually compare this rate to the latest LQ command */ | 1139 | /* Here we actually compare this rate to the latest LQ command */ |
1113 | if (!rs_rate_equal(&tx_resp_rate, &lq_rate)) { | 1140 | if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { |
1114 | IWL_DEBUG_RATE(mvm, | 1141 | IWL_DEBUG_RATE(mvm, |
1115 | "initial tx resp rate 0x%x does not match 0x%x\n", | 1142 | "initial tx resp rate 0x%x does not match 0x%x\n", |
1116 | tx_resp_hwrate, lq_hwrate); | 1143 | tx_resp_hwrate, lq_hwrate); |