Index: head/sys/dev/usb/wlan/if_run.c =================================================================== --- head/sys/dev/usb/wlan/if_run.c +++ head/sys/dev/usb/wlan/if_run.c @@ -64,6 +64,9 @@ #include #include #include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif #include #include @@ -495,6 +498,9 @@ static void run_init_locked(struct run_softc *); static void run_stop(void *); static void run_delay(struct run_softc *, u_int); +static void run_update_chw(struct ieee80211com *ic); +static int run_ampdu_enable(struct ieee80211_node *ni, + struct ieee80211_tx_ampdu *tap); static eventhandler_tag run_etag; @@ -506,10 +512,13 @@ uint16_t sp_ack_dur; uint16_t lp_ack_dur; } rt2860_rates[] = { + /* CCK rates (11b) */ { 2, 0, IEEE80211_T_DS, 0, 314, 314 }, { 4, 1, IEEE80211_T_DS, 1, 258, 162 }, { 11, 2, IEEE80211_T_DS, 2, 223, 127 }, { 22, 3, IEEE80211_T_DS, 3, 213, 117 }, + + /* OFDM rates (11a / 11g) */ { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 }, { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 }, { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 }, @@ -517,9 +526,35 @@ { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 }, { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 }, { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 }, - { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 } + { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 }, + + /* MCS - single stream */ + { 0x80, 0, IEEE80211_T_HT, 4, 60, 60 }, + { 0x81, 1, IEEE80211_T_HT, 4, 60, 60 }, + { 0x82, 2, IEEE80211_T_HT, 4, 60, 60 }, + { 0x83, 3, IEEE80211_T_HT, 4, 60, 60 }, + { 0x84, 4, IEEE80211_T_HT, 4, 60, 60 }, + { 0x85, 5, IEEE80211_T_HT, 4, 60, 60 }, + { 0x86, 6, IEEE80211_T_HT, 4, 60, 60 }, + { 0x87, 7, IEEE80211_T_HT, 4, 60, 60 }, + /* MCS - 2 streams */ + { 0x88, 8, IEEE80211_T_HT, 4, 60, 60 }, + { 0x89, 9, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8a, 10, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8b, 11, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8c, 12, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8d, 13, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8e, 14, IEEE80211_T_HT, 4, 60, 60 }, + { 0x8f, 15, IEEE80211_T_HT, 4, 60, 60 }, }; +/* These are indexes into the above rt2860_rates[] array */ +#define RT2860_RIDX_CCK1 0 +#define RT2860_RIDX_CCK11 3 +#define RT2860_RIDX_OFDM6 4 +#define RT2860_RIDX_MCS0 12 +#define RT2860_RIDX_MAX 28 + static const struct { uint16_t reg; uint32_t val; @@ -807,9 +842,25 @@ IEEE80211_C_MBSS | IEEE80211_C_SHPREAMBLE | /* short preamble supported */ IEEE80211_C_SHSLOT | /* short slot time supported */ + IEEE80211_C_SWAMSDUTX | /* Do software A-MSDU TX */ + IEEE80211_C_FF | /* Atheros fast-frames */ IEEE80211_C_WME | /* WME */ IEEE80211_C_WPA; /* WPA1|WPA2(RSN) */ + ic->ic_htcaps = + IEEE80211_HTC_HT | + IEEE80211_HTC_AMPDU | + IEEE80211_HTC_AMSDU | + IEEE80211_HTCAP_MAXAMSDU_3839 | + IEEE80211_HTCAP_SMPS_OFF; + + /* + * For now, just do 1 stream. Later on we'll figure out + * how many tx/rx streams a particular NIC supports. + */ + ic->ic_rxstream = 1; + ic->ic_txstream = 1; + ic->ic_cryptocaps = IEEE80211_CRYPTO_WEP | IEEE80211_CRYPTO_AES_CCM | @@ -839,6 +890,8 @@ ic->ic_vap_delete = run_vap_delete; ic->ic_transmit = run_transmit; ic->ic_parent = run_parent; + ic->ic_update_chw = run_update_chw; + ic->ic_ampdu_enable = run_ampdu_enable; ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), @@ -974,6 +1027,10 @@ vap->iv_update_beacon = run_update_beacon; vap->iv_max_aid = RT2870_WCID_MAX; + + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_2; + /* * To delete the right key from h/w, we need wcid. * Luckily, there is unused space in ieee80211_key{}, wk_pad, @@ -2059,11 +2116,13 @@ struct ieee80211_node *ni; struct run_node *rn; + /* XXX TODO: methodize with MCS rates */ rate = ic->ic_sup_rates[ic->ic_curmode]. rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL; for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == rate) break; + ni = ieee80211_ref_node(vap->iv_bss); rn = RUN_NODE(ni); rn->fix_ridx = ridx; @@ -2605,7 +2664,7 @@ struct run_node *rn = RUN_NODE(ni); union run_stats sta[2]; uint16_t (*wstat)[3]; - int error; + int error, ridx; RUN_LOCK(sc); @@ -2656,12 +2715,17 @@ } ieee80211_ratectl_tx_update(vap, txs); - rn->amrr_ridx = ieee80211_ratectl_rate(ni, NULL, 0); + ieee80211_ratectl_rate(ni, NULL, 0); + /* XXX TODO: methodize with MCS rates */ + for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) + if (rt2860_rates[ridx].rate == ni->ni_txrate) + break; + rn->amrr_ridx = ridx; fail: RUN_UNLOCK(sc); - RUN_DPRINTF(sc, RUN_DEBUG_RATE, "ridx=%d\n", rn->amrr_ridx); + RUN_DPRINTF(sc, RUN_DEBUG_RATE, "rate=%d, ridx=%d\n", ni->ni_txrate, rn->amrr_ridx); } static void @@ -2684,14 +2748,12 @@ run_newassoc(struct ieee80211_node *ni, int isnew) { struct run_node *rn = RUN_NODE(ni); - struct ieee80211_rateset *rs = &ni->ni_rates; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_softc; uint8_t rate; uint8_t ridx; uint8_t wcid; - int i, j; wcid = (vap->iv_opmode == IEEE80211_M_STA) ? 1 : RUN_AID2WCID(ni->ni_associd); @@ -2721,31 +2783,8 @@ "new assoc isnew=%d associd=%x addr=%s\n", isnew, ni->ni_associd, ether_sprintf(ni->ni_macaddr)); - for (i = 0; i < rs->rs_nrates; i++) { - rate = rs->rs_rates[i] & IEEE80211_RATE_VAL; - /* convert 802.11 rate to hardware rate index */ - for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) - if (rt2860_rates[ridx].rate == rate) - break; - rn->ridx[i] = ridx; - /* determine rate of control response frames */ - for (j = i; j >= 0; j--) { - if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && - rt2860_rates[rn->ridx[i]].phy == - rt2860_rates[rn->ridx[j]].phy) - break; - } - if (j >= 0) { - rn->ctl_ridx[i] = rn->ridx[j]; - } else { - /* no basic rate found, use mandatory one */ - rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx; - } - RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE, - "rate=0x%02x ridx=%d ctl_ridx=%d\n", - rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]); - } rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate; + /* XXX TODO: methodize with MCS rates */ for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == rate) break; @@ -2876,6 +2915,10 @@ } else ni = NULL; + if(ni && ni->ni_flags & IEEE80211_NODE_HT) { + m->m_flags |= M_AMPDU; + } + if (__predict_false(flags & RT2860_RX_MICERR)) { /* report MIC failures to net80211 for TKIP */ if (ni != NULL) @@ -3089,6 +3132,9 @@ /* make sure we free the source buffer, if any */ m_freem(m); +#ifdef IEEE80211_SUPPORT_SUPERG + ieee80211_ff_age_all(ic, 100); +#endif RUN_LOCK(sc); } @@ -3234,6 +3280,15 @@ } break; } +#ifdef IEEE80211_SUPPORT_SUPERG + /* XXX TODO: make this deferred rather than unlock/relock */ + /* XXX TODO: should only do the QoS AC this belongs to */ + if (pq->tx_nfree >= RUN_TX_RING_COUNT) { + RUN_UNLOCK(sc); + ieee80211_ff_flush_all(ic); + RUN_LOCK(sc); + } +#endif } static void @@ -3318,15 +3373,21 @@ if (ridx != RT2860_RIDX_CCK1 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) mcs |= RT2860_PHY_SHPRE; - } else + } else if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) { mcs |= RT2860_PHY_OFDM; + } else if (rt2860_rates[ridx].phy == IEEE80211_T_HT) { + /* XXX TODO: [adrian] set short preamble for MCS? */ + mcs |= RT2860_PHY_HT; /* Mixed, not greenfield */ + } txwi->phy = htole16(mcs); /* check if RTS/CTS or CTS-to-self protection is required */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold || + ((m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) || ((ic->ic_flags & IEEE80211_F_USEPROT) && - rt2860_rates[ridx].phy == IEEE80211_T_OFDM))) + rt2860_rates[ridx].phy == IEEE80211_T_OFDM) || + ((ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) && + rt2860_rates[ridx].phy == IEEE80211_T_HT))) txwi->txop |= RT2860_TX_TXOP_HT; else txwi->txop |= RT2860_TX_TXOP_BACKOFF; @@ -3390,7 +3451,8 @@ /* pickup a rate index */ if (IEEE80211_IS_MULTICAST(wh->i_addr1) || type != IEEE80211_FC0_TYPE_DATA || m->m_flags & M_EAPOL) { - ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? + /* XXX TODO: methodize for 11n; use MCS0 for 11NA/11NG */ + ridx = (ic->ic_curmode == IEEE80211_MODE_11A || ic->ic_curmode == IEEE80211_MODE_11NA) ? RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; ctl_ridx = rt2860_rates[ridx].ctl_ridx; } else { @@ -3609,6 +3671,7 @@ data->m = mprot; data->ni = ieee80211_ref_node(ni); + /* XXX TODO: methodize with MCS rates */ for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == protrate) break; @@ -3684,6 +3747,7 @@ data->m = m; data->ni = ni; + /* XXX TODO: methodize with MCS rates */ for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == rate) break; @@ -4856,12 +4920,17 @@ memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); + setbit(bands, IEEE80211_MODE_11NG); + + /* Note: for now, only support HT20 channels */ ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); 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); + setbit(bands, IEEE80211_MODE_11NA); + /* Note: for now, only support HT20 channels */ ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, run_chan_5ghz, nitems(run_chan_5ghz), bands, 0); } @@ -6205,6 +6274,10 @@ /* turn radio LED on */ run_set_leds(sc, RT2860_LED_RADIO); + /* Set up AUTO_RSP_CFG register for auto response */ + run_write(sc, RT2860_AUTO_RSP_CFG, RT2860_AUTO_RSP_EN | + RT2860_BAC_ACKPOLICY_EN | RT2860_CTS_40M_MODE_EN); + sc->sc_flags |= RUN_RUNNING; sc->cmdq_run = RUN_CMDQ_GO; @@ -6309,6 +6382,22 @@ { usb_pause_mtx(mtx_owned(&sc->sc_mtx) ? &sc->sc_mtx : NULL, USB_MS_TO_TICKS(ms)); +} + + +static void +run_update_chw(struct ieee80211com *ic) +{ + + printf("%s: TODO\n", __func__); +} + +static int +run_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) +{ + + /* For now, no A-MPDU TX support in the driver */ + return (0); } static device_method_t run_methods[] = { Index: head/sys/dev/usb/wlan/if_runreg.h =================================================================== --- head/sys/dev/usb/wlan/if_runreg.h +++ head/sys/dev/usb/wlan/if_runreg.h @@ -955,11 +955,6 @@ #define RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ 0x14e #define RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ 0x14f -#define RT2860_RIDX_CCK1 0 -#define RT2860_RIDX_CCK11 3 -#define RT2860_RIDX_OFDM6 4 -#define RT2860_RIDX_MAX 12 - /* * EEPROM access macro. */ Index: head/sys/dev/usb/wlan/if_runvar.h =================================================================== --- head/sys/dev/usb/wlan/if_runvar.h +++ head/sys/dev/usb/wlan/if_runvar.h @@ -97,8 +97,6 @@ struct run_node { struct ieee80211_node ni; - uint8_t ridx[IEEE80211_RATE_MAXSIZE]; - uint8_t ctl_ridx[IEEE80211_RATE_MAXSIZE]; uint8_t amrr_ridx; uint8_t mgt_ridx; uint8_t fix_ridx;