Index: sys/dev/usb/wlan/if_run.c =================================================================== --- sys/dev/usb/wlan/if_run.c +++ sys/dev/usb/wlan/if_run.c @@ -79,8 +79,14 @@ #define RUN_DEBUG #endif +#define IF_RUN_11N +/* #undef IF_RUN_11N */ +#undef IF_RUN_11N_AMDPU +#undef IF_RUN_11N_5GHZ +#define RUN_DEBUG + #ifdef RUN_DEBUG -int run_debug = 0; +int run_debug = 0x00000020; static SYSCTL_NODE(_hw_usb, OID_AUTO, run, CTLFLAG_RW, 0, "USB run"); SYSCTL_INT(_hw_usb_run, OID_AUTO, debug, CTLFLAG_RWTUN, &run_debug, 0, "run debug level"); @@ -808,6 +814,35 @@ IEEE80211_C_WME | /* WME */ IEEE80211_C_WPA; /* WPA1|WPA2(RSN) */ +#ifdef IF_RUN_11N + /* set device HT capabilities */ + /* HT Capabilities strictly for 11ng (we dont support 11ac yet..) */ + + // copied from linux for now + uint16_t cap80211 = 0x03bc; + + ic->ic_htcaps = + IEEE80211_HTC_HT | IEEE80211_HTC_RXMCS32 | IEEE80211_HTC_TXMCS32 | cap80211; + ic->ic_rxstream = 3; + ic->ic_txstream = 3; + + /* IEEE80211_HTC_AMPDU | */ + /* IEEE80211_HTCAP_CHWIDTH40 | */ + /* IEEE80211_HTCAP_SHORTGI40 | */ + /* IEEE80211_HTCAP_GREENFIELD | */ + /* IEEE80211_HTCAP_SMPS_OFF | */ + /* IEEE80211_HTCAP_SHORTGI20 | */ + /* IEEE80211_HTCAP_TXSTBC | */ + /* IEEE80211_HTCAP_RXSTBC_3STREAM | */ + /* IEEE80211_HTCAP_MAXRXAMPDU | */ + /* IEEE80211_HTCAP_MPDUDENSITY_4 | */ + /* IEEE80211_HTC_TXMCS32) & */ + /* (~IEEE80211_HTCAP_LDPC); */ + + /* IEEE80211_HTCAP_DSSSCCK40 | */ + device_printf(sc->sc_dev, "ic_htcaps = 0x%x\n", ic->ic_htcaps); + device_printf(sc->sc_dev, "ic_htcaps has CH40 = %s\n, has SGI40 %s\n", ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) == 0) ? "nope" : "Yes", ((ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40) == 0) ? "nope" : "Yes"); +#endif ic->ic_cryptocaps = IEEE80211_CRYPTO_WEP | IEEE80211_CRYPTO_AES_CCM | @@ -972,6 +1007,11 @@ vap->iv_update_beacon = run_update_beacon; vap->iv_max_aid = RT2870_WCID_MAX; +#ifdef IF_RUN_11N_AMDPU + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_2; +#endif + /* * To delete the right key from h/w, we need wcid. * Luckily, there is unused space in ieee80211_key{}, wk_pad, @@ -2701,7 +2741,6 @@ /* only interested in true associations */ if (isnew && ni->ni_associd != 0) { - /* * This function could is called though timeout function. * Need to defer. @@ -2964,7 +3003,7 @@ switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: - RUN_DPRINTF(sc, RUN_DEBUG_RECV, + RUN_DPRINTF(sc, RUN_DEBUG_RECV, "rx done, actlen=%d\n", xferlen); if (xferlen < (int)(sizeof(uint32_t) + rxwisize + @@ -3308,6 +3347,15 @@ /* setup TX Wireless Information */ txwi = (struct rt2860_txwi *)(txd + 1); txwi->len = htole16(m->m_pkthdr.len - pad); + +#ifdef IF_RUN_11N + /* Use the HT_MIX PHY in txwi */ + if (IEEE80211_IS_CHAN_HT20(ic->ic_curchan)) { + printf("%s: using mix ht!\n", __func__); + mcs |= RT2860_PHY_HT_MIX; + // XXX: Short preamble? + } else +#endif if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { mcs |= RT2860_PHY_CCK; if (ridx != RT2860_RIDX_CCK1 && @@ -3315,6 +3363,7 @@ mcs |= RT2860_PHY_SHPRE; } else mcs |= RT2860_PHY_OFDM; + txwi->phy = htole16(mcs); /* check if RTS/CTS or CTS-to-self protection is required */ @@ -4845,21 +4894,34 @@ run_getradiocaps(struct ieee80211com *ic, int maxchans, int *nchans, struct ieee80211_channel chans[]) { + +#ifdef IF_RUN_11N_5GHZ // disable 5ghz for now struct run_softc *sc = ic->ic_softc; +#endif uint8_t bands[IEEE80211_MODE_BYTES]; + int ht40 = 0; memset(bands, 0, sizeof(bands)); + +#ifdef IF_RUN_11N + setbit(bands, IEEE80211_MODE_11NG); + setbit(bands, IEEE80211_MODE_11G); + ht40 = 0; +#else setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); - ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); +#endif + ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, ht40); +#ifdef IF_RUN_11N_5GHZ //disable 5ghz for now if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 || sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 || sc->rf_rev == RT5592_RF_5592) { setbit(bands, IEEE80211_MODE_11A); ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, - run_chan_5ghz, nitems(run_chan_5ghz), bands, 0); + run_chan_5ghz, nitems(run_chan_5ghz), bands, ht40); } +#endif } static void @@ -5218,6 +5280,9 @@ { struct ieee80211com *ic = &sc->sc_ic; + RUN_DPRINTF(sc, RUN_DEBUG_ANY, + "Mode in %s is 0x%x\n", __func__, ic->ic_curmode); + /* set basic rates mask */ if (ic->ic_curmode == IEEE80211_MODE_11B) run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x003); Index: sys/dev/usb/wlan/if_runreg.h =================================================================== --- sys/dev/usb/wlan/if_runreg.h +++ sys/dev/usb/wlan/if_runreg.h @@ -781,7 +781,7 @@ #define RT2860_PHY_MODE 0xc000 #define RT2860_PHY_CCK (0 << 14) #define RT2860_PHY_OFDM (1 << 14) -#define RT2860_PHY_HT (2 << 14) +#define RT2860_PHY_HT_MIX (2 << 14) #define RT2860_PHY_HT_GF (3 << 14) #define RT2860_PHY_SGI (1 << 8) #define RT2860_PHY_BW40 (1 << 7) Index: sys/net80211/ieee80211.c =================================================================== --- sys/net80211/ieee80211.c +++ sys/net80211/ieee80211.c @@ -120,6 +120,7 @@ /* NB: OFDM rates are handled specially based on mode */ static const struct ieee80211_rateset ieee80211_rateset_11g = { 12, { B(2), B(4), B(11), B(22), 12, 18, 24, 36, 48, 72, 96, 108 } }; + /* { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; */ #undef B static int set_vht_extchan(struct ieee80211_channel *c); @@ -206,6 +207,7 @@ if (IEEE80211_IS_CHAN_VHTG(c)) setbit(ic->ic_modecaps, IEEE80211_MODE_VHT_2GHZ); } + /* initialize candidate channels to all available */ memcpy(ic->ic_chan_active, ic->ic_chan_avail, sizeof(ic->ic_chan_avail)); @@ -1238,7 +1240,7 @@ if (*nchans >= maxchans) return (ENOBUFS); -#if 0 +#if 1 printf("%s: %d: ieee=%d, freq=%d, flags=0x%08x\n", __func__, *nchans, @@ -1272,7 +1274,7 @@ if (*nchans >= maxchans) return (ENOBUFS); -#if 0 +#if 1 printf("%s: %d: flags=0x%08x\n", __func__, *nchans, @@ -1630,6 +1632,14 @@ getflags_2ghz(bands, flags, ht40); KASSERT(flags[0] != 0, ("%s: no correct mode provided\n", __func__)); +#if 1 + for(int i = 0; flags[i] != 0; i++) + printf("%s: flags[%d] = 0x%x\n", + __func__, + i, + flags[i]); +#endif + return (add_chanlist(chans, maxchans, nchans, ieee, nieee, flags)); } Index: sys/net80211/ieee80211_ht.c =================================================================== --- sys/net80211/ieee80211_ht.c +++ sys/net80211/ieee80211_ht.c @@ -255,7 +255,6 @@ void ieee80211_ht_vattach(struct ieee80211vap *vap) { - /* driver can override defaults */ vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_8K; vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_NA; @@ -2703,7 +2702,6 @@ uint8_t *frm; int tid, ret; - IEEE80211_NOTE(tap->txa_ni->ni_vap, IEEE80211_MSG_11N, tap->txa_ni, "%s: called", @@ -2994,8 +2992,14 @@ txparams |= (ic->ic_txstream - 1) << 2; /* num TX streams */ if (ic->ic_htcaps & IEEE80211_HTC_TXUNEQUAL) txparams |= 0x16; /* TX unequal modulation sup */ - } else - txparams = 0; + } else { + /* lrx337 XXX: This was 0, but changed to 1 in order to mimic rt2x00 behavior. + Shouldn't this if else block take into consideration other htcaps like + IEEE80211_HTC_TXMCS32 for setting txparams = 0x1 and then check if the + num streams are equal for TX RX MCS not equal (is it enough to check the + num rx / tx streams to conclude that MCS sets are unequal?). */ + txparams = 0x0; + } frm[12] = txparams; } Index: sys/net80211/ieee80211_node.c =================================================================== --- sys/net80211/ieee80211_node.c +++ sys/net80211/ieee80211_node.c @@ -761,6 +761,11 @@ ieee80211_sync_curchan(struct ieee80211com *ic) { struct ieee80211_channel *c; + printf("%s: curchan freq %d flags 0x%x\nhtadjflags 0x%x\n", + __func__, + ic->ic_curchan->ic_freq, + ic->ic_curchan->ic_flags, + gethtadjustflags(ic)); c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan, gethtadjustflags(ic)); c = ieee80211_vht_adjust_channel(ic, c, getvhtadjustflags(ic)); @@ -773,6 +778,8 @@ ic->ic_set_channel(ic); ieee80211_radiotap_chan_change(ic); IEEE80211_LOCK(ic); + } else { + printf("%s: did not change channel\n", __func__); } } Index: sys/net80211/ieee80211_output.c =================================================================== --- sys/net80211/ieee80211_output.c +++ sys/net80211/ieee80211_output.c @@ -2415,6 +2415,12 @@ frm = ieee80211_add_htcap_ch(frm, vap, c); } + /* If we are in STA mode and have HT caps, advertise them. Don't upgrade to an + HT channel just yet. */ + if ((vap->iv_opmode == IEEE80211_M_STA) && (vap->iv_flags_ht & IEEE80211_FHT_HT)) { + frm = ieee80211_add_htcap_ch(frm, vap, ic->ic_curchan); + } + /* * XXX TODO: need to figure out what/how to update the * VHT channel.