-/* $OpenBSD: ieee80211.h,v 1.58 2016/05/12 18:18:48 dcoppa Exp $ */
+/* $OpenBSD: ieee80211.h,v 1.59 2017/04/23 21:04:55 stsp Exp $ */
/* $NetBSD: ieee80211.h,v 1.6 2004/04/30 23:51:53 dyoung Exp $ */
/*-
/* Bits 96-100: Tx MCS set */
#define IEEE80211_TX_MCS_SET_DEFINED 0x01
#define IEEE80211_TX_RX_MCS_NOT_EQUAL 0x02
-#define IEEE80211_TX_SPATIAL_STREAMS 0x18
-#define IEEE80211_TX_UNEQUAL_MODULATION 0x20
+#define IEEE80211_TX_SPATIAL_STREAMS 0x0c
+#define IEEE80211_TX_UNEQUAL_MODULATION 0x10
/* Bits 101-127: Reserved */
/*
-/* $OpenBSD: ieee80211_mira.c,v 1.10 2017/01/28 16:01:36 stsp Exp $ */
+/* $OpenBSD: ieee80211_mira.c,v 1.11 2017/04/23 21:04:55 stsp Exp $ */
/*
* Copyright (c) 2016 Stefan Sperling <stsp@openbsd.org>
struct ieee80211_node *);
void ieee80211_mira_probe_next_rate(struct ieee80211_mira_node *,
struct ieee80211_node *);
+int ieee80211_mira_valid_tx_mcs(struct ieee80211com *, int);
uint32_t ieee80211_mira_valid_rates(struct ieee80211com *,
struct ieee80211_node *);
uint32_t ieee80211_mira_mcs_below(struct ieee80211_mira_node *, int);
ni->ni_txmcs = ieee80211_mira_next_mcs(mn, ni);
}
+int
+ieee80211_mira_valid_tx_mcs(struct ieee80211com *ic, int mcs)
+{
+ uint32_t ntxstreams = 1;
+ static const int max_mcs[] = { 7, 15, 23, 31 };
+
+ if ((ic->ic_tx_mcs_set & IEEE80211_TX_RX_MCS_NOT_EQUAL) == 0)
+ return isset(ic->ic_sup_mcs, mcs);
+
+ ntxstreams += ((ic->ic_tx_mcs_set & IEEE80211_TX_SPATIAL_STREAMS) >> 2);
+ if (ntxstreams < 1 || ntxstreams > 4)
+ panic("invalid number of Tx streams: %u", ntxstreams);
+ return (mcs <= max_mcs[ntxstreams - 1] && isset(ic->ic_sup_mcs, mcs));
+}
+
uint32_t
ieee80211_mira_valid_rates(struct ieee80211com *ic, struct ieee80211_node *ni)
{
for (i = 0;
i < MIN(IEEE80211_MIRA_NUM_MCS, IEEE80211_HT_NUM_MCS); i++) {
- if (isset(ic->ic_sup_mcs, i) && isset(ni->ni_rxmcs, i))
- valid_mcs |= (1 << i);
+ if (!isset(ni->ni_rxmcs, i))
+ continue;
+ if (!ieee80211_mira_valid_tx_mcs(ic, i))
+ continue;
+ valid_mcs |= (1 << i);
}
return valid_mcs;