[run] Add initial 802.11n support.
* Enable self-generated 11n frames * add MCS rates for 1-stream and 2-stream rates; will do 3-stream once the rest of this tests out OK with other people. * Hard-code 1 stream for now * Add A-MPDU RX mbuf tagging * RTS/CTS if doing RTSCTS in HT protmode as well as legacy; they're separate configuration flags * Update the amrr rate index stuff - walk the rates array like others to find the right one - this now works for MCS and CCK/OFDM rates * Add support for atheros fast frames/AMSDU support as we can generate those in net80211. TODO: * HT40 isn't enabled yet * No A-MPDU support just yet; that requires some more firmware research and maybe porting some ath(4) A-MPDU support/tracking into net80211 * Short preamble flags aren't set yet for MCS; need to check the linux driver and see what's going on there * Add 3x3 rates and set tx/rx stream configuration appropriately * More 5GHz testing; I have a 3x3 dual band USB NIC coming soon that'll let me test this. * Figure out why the RX path isn't performing as fast as it could - there's only a single buffer loaded at a time for the receive path in the USB bulk handler and this may not be super useful. Tested: * RT5390 usb, 1x1, RF5370 (2GHz radio), STA mode - A-MSDU TX, A-MPDU RX Submitted by: Ashish Gupta <ashishgu@andrew.cmu.edu> Differential Revision: https://reviews.freebsd.org/D22840
This commit is contained in:
parent
dbcf7598b0
commit
f520d76129
@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net80211/ieee80211_regdomain.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
#include <net80211/ieee80211_superg.h>
|
||||
#endif
|
||||
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usbdi.h>
|
||||
@ -495,6 +498,9 @@ static void run_adjust_freq_offset(struct run_softc *);
|
||||
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 @@ static const struct rt2860_rate {
|
||||
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 @@ static const struct rt2860_rate {
|
||||
{ 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 @@ run_attach(device_t self)
|
||||
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 @@ run_attach(device_t self)
|
||||
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 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
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 @@ run_media_change(struct ifnet *ifp)
|
||||
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 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
|
||||
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 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
|
||||
}
|
||||
|
||||
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 @@ static void
|
||||
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 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
|
||||
"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 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
|
||||
} 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 @@ tr_setup:
|
||||
/* 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 @@ tr_setup:
|
||||
}
|
||||
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 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
|
||||
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 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
||||
/* 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 @@ run_sendprot(struct run_softc *sc,
|
||||
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 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
|
||||
|
||||
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 @@ run_getradiocaps(struct ieee80211com *ic,
|
||||
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 @@ run_init_locked(struct run_softc *sc)
|
||||
/* 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;
|
||||
|
||||
@ -6311,6 +6384,22 @@ run_delay(struct run_softc *sc, u_int ms)
|
||||
&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[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, run_match),
|
||||
|
@ -955,11 +955,6 @@ struct rt2860_rxwi {
|
||||
#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.
|
||||
*/
|
||||
|
@ -97,8 +97,6 @@ STAILQ_HEAD(run_tx_data_head, run_tx_data);
|
||||
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user