rate->ldpc = true;
if (ucode_rate & RATE_MCS_VHT_STBC_MSK)
rate->stbc = true;
+ if (ucode_rate & RATE_MCS_BF_MSK)
+ rate->bfer = true;
rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
if (nss == 1) {
rate->type = LQ_HT_SISO;
- WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
+ WARN_ONCE(!rate->stbc && !rate->bfer && num_of_ant != 1,
+ "stbc %d bfer %d",
+ rate->stbc, rate->bfer);
} else if (nss == 2) {
rate->type = LQ_HT_MIMO2;
WARN_ON_ONCE(num_of_ant != 2);
if (nss == 1) {
rate->type = LQ_VHT_SISO;
- WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
+ WARN_ONCE(!rate->stbc && !rate->bfer && num_of_ant != 1,
+ "stbc %d bfer %d",
+ rate->stbc, rate->bfer);
} else if (nss == 2) {
rate->type = LQ_VHT_MIMO2;
WARN_ON_ONCE(num_of_ant != 2);
rs_get_lower_rate_in_column(lq_sta, rate);
}
-/* Check if both rates are identical */
+/* Check if both rates are identical
+ * allow_ant_mismatch enables matching a SISO rate on ANT_A or ANT_B
+ * with a rate indicating STBC/BFER and ANT_AB.
+ */
static inline bool rs_rate_equal(struct rs_rate *a,
- struct rs_rate *b)
-{
+ struct rs_rate *b,
+ bool allow_ant_mismatch)
+
+{
+ bool ant_match = (a->ant == b->ant) && (a->stbc == b->stbc) &&
+ (a->bfer == b->bfer);
+
+ if (allow_ant_mismatch) {
+ if (a->stbc || a->bfer) {
+ WARN_ONCE(a->ant != ANT_AB, "stbc %d bfer %d ant %d",
+ a->stbc, a->bfer, a->ant);
+ ant_match |= (b->ant == ANT_A || b->ant == ANT_B);
+ } else if (b->stbc || b->bfer) {
+ WARN_ONCE(b->ant != ANT_AB, "stbc %d bfer %d ant %d",
+ b->stbc, b->bfer, b->ant);
+ ant_match |= (a->ant == ANT_A || a->ant == ANT_B);
+ }
+ }
+
return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) &&
- (a->ldpc == b->ldpc) && (a->index == b->index) &&
- (a->ant == b->ant);
+ (a->ldpc == b->ldpc) && (a->index == b->index) && ant_match;
}
/* Check if both rates share the same column */
{
bool ant_match;
- if (a->stbc)
+ if (a->stbc || a->bfer)
ant_match = (b->ant == ANT_A || b->ant == ANT_B);
else
ant_match = (a->ant == b->ant);
u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta;
+ bool allow_ant_mismatch = mvm->fw->ucode_capa.api[0] &
+ IWL_UCODE_TLV_API_LQ_SS_PARAMS;
/* Treat uninitialized rate scaling data same as non-existing. */
if (!lq_sta) {
rs_rate_from_ucode_rate(tx_resp_hwrate, info->band, &tx_resp_rate);
/* Here we actually compare this rate to the latest LQ command */
- if (!rs_rate_equal(&tx_resp_rate, &lq_rate)) {
+ if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) {
IWL_DEBUG_RATE(mvm,
"initial tx resp rate 0x%x does not match 0x%x\n",
tx_resp_hwrate, lq_hwrate);