aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/rs.c
diff options
context:
space:
mode:
authorEyal Shapira <eyal@wizery.com>2015-01-29 18:38:29 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-01 09:55:03 -0500
commitba69d0e36261234efa315ff34ef6f59da9f98ac3 (patch)
tree65657e6d88668e2ca12752f01b8503098bd6cf79 /drivers/net/wireless/iwlwifi/mvm/rs.c
parent0b8d17f30304bedff77d47450839865048b1b626 (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.c45
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 */
1012static inline bool rs_rate_equal(struct rs_rate *a, 1021static 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);