On Wed, Apr 19, 2017 at 10:08:01AM +0200, Stefan Sperling wrote:
> On Tue, Apr 18, 2017 at 11:29:22PM -0500, Colton Lewis wrote:
> > > Can you show me a dmesg please, specifically the lines which are
> > > related to your wifi card?
> 
> > athn0 at pci6 dev 0 function 0 "Atheros AR9281" rev 0x01: apic 8 int 17
> > athn0: AR9280 rev 2 (1T2R), ROM rev 11, address 00:15:af:cd:f2:4f
> 
> Thank you! This confirms my suspicion that your wifi card is a weird one.
> It can receive MIMO but cannot send MIMO (2 Rx chains but only 1 Tx chain).
> 
> Likely there's a bug in the code which fails to account for this situation.
> AFAIK this kind of device has not been tested before.
> 
> I'll take a look.

Please try this patch.

This patch makes unequal numbers of Tx and Rx streams work in 11n mode.
I have tested this patch by artificially limiting iwm(4) to one Tx stream.
This works as expected (AP sends with two streams, iwm(4) sends with one).

I still cannot explain why 11g mode became worse for you such that only 11b
mode works. I cannot recall any change which would make a difference between
6.0 and 6.1 in that regard. Are you sure you were testing 11g mode correctly?
When you switched your athn client to 11g mode, did your AP follow this change
or did it continue treating your client as 11n capable? A quirk like that
would explain this discrepancy.

Index: sys/net80211/ieee80211.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211.h,v
retrieving revision 1.58
diff -u -p -r1.58 ieee80211.h
--- sys/net80211/ieee80211.h    12 May 2016 18:18:48 -0000      1.58
+++ sys/net80211/ieee80211.h    19 Apr 2017 13:47:13 -0000
@@ -612,8 +612,8 @@ enum {
 /* 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 */
 
 /*
Index: sys/net80211/ieee80211_mira.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_mira.c,v
retrieving revision 1.10
diff -u -p -r1.10 ieee80211_mira.c
--- sys/net80211/ieee80211_mira.c       28 Jan 2017 16:01:36 -0000      1.10
+++ sys/net80211/ieee80211_mira.c       20 Apr 2017 09:37:53 -0000
@@ -81,6 +81,7 @@ int   ieee80211_mira_check_probe_timers(st
            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);
@@ -991,6 +992,21 @@ ieee80211_mira_probe_next_rate(struct ie
        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)
 {
@@ -999,8 +1015,11 @@ ieee80211_mira_valid_rates(struct ieee80
 
        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;

Reply via email to