Index: sys/dev/urtwn/if_urtwn.c =================================================================== --- sys/dev/urtwn/if_urtwn.c (revision 297058) +++ sys/dev/urtwn/if_urtwn.c (working copy) @@ -109,6 +109,9 @@ #define IEEE80211_HAS_ADDR4(wh) IEEE80211_IS_DSTODS(wh) +static int urtwn_enable_11n = 1; +TUNABLE_INT("hw.usb.urtwn.enable_11n", &urtwn_enable_11n); + /* various supported device vendors/products */ static const STRUCT_USB_HOST_ID urtwn_devs[] = { #define URTWN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } @@ -465,7 +468,20 @@ return (usbd_lookup_id_by_uaa(urtwn_devs, sizeof(urtwn_devs), uaa)); } +static void +urtwn_update_chw(struct ieee80211com *ic) +{ +} + static int +urtwn_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) +{ + + /* We're driving this ourselves (eventually); don't involve net80211 */ + return (0); +} + +static int urtwn_attach(device_t self) { struct usb_attach_arg *uaa = device_get_ivars(self); @@ -565,9 +581,28 @@ IEEE80211_CRYPTO_TKIP | IEEE80211_CRYPTO_AES_CCM; + /* Assume they're all 11n capable for now */ + if (1 && urtwn_enable_11n) { + device_printf(self, "enabling 11n\n"); + ic->ic_htcaps = IEEE80211_HTC_HT | + IEEE80211_HTC_AMPDU | + IEEE80211_HTC_AMSDU | + IEEE80211_HTCAP_MAXAMSDU_3839 | + IEEE80211_HTCAP_SMPS_OFF; + /* no HT40 just yet */ + // ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40; + + /* XXX TODO: verify chains versus streams for urtwn */ + ic->ic_txstream = sc->ntxchains; + ic->ic_rxstream = sc->nrxchains; + } + memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); + if (1 && urtwn_enable_11n) { + setbit(bands, IEEE80211_MODE_11NG); + } ieee80211_init_channels(ic, NULL, bands); ieee80211_ifattach(ic); @@ -589,6 +624,8 @@ sc->sc_node_free = ic->ic_node_free; ic->ic_node_free = urtwn_r88e_node_free; } + ic->ic_update_chw = urtwn_update_chw; + ic->ic_ampdu_enable = urtwn_ampdu_enable; ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), URTWN_TX_RADIOTAP_PRESENT, @@ -1081,6 +1118,8 @@ nf = URTWN_NOISE_FLOOR; if (ni != NULL) { + if (ni->ni_flags & IEEE80211_NODE_HT) + m->m_flags |= M_AMPDU; (void)ieee80211_input(ni, m, rssi - nf, nf); ieee80211_free_node(ni); } else { @@ -1827,7 +1866,7 @@ struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni; - struct ieee80211_rateset *rs; + struct ieee80211_rateset *rs, *rs_ht; struct r92c_fw_cmd_macid_cfg cmd; uint32_t rates, basicrates; uint8_t mode; @@ -1839,6 +1878,8 @@ /* Get normal and basic rates mask. */ rates = basicrates = 0; maxrate = maxbasicrate = 0; + + /* This is for 11bg */ for (i = 0; i < rs->rs_nrates; i++) { /* Convert 802.11 rate to HW rate index. */ for (j = 0; j < nitems(ridx2rate); j++) @@ -1856,6 +1897,24 @@ maxbasicrate = j; } } + + /* If we're doing 11n, enable 11n rates */ + if (ni->ni_flags & IEEE80211_NODE_HT) { + rs_ht = &ni->ni_rates; + for (i = 0; i < rs_ht->rs_nrates; i++) { + /* 11n rates start at index 12 */ + j |= ((rs_ht->rs_rates[i]) & 0x1f) + 12; + rates |= (1 << j); + if (j > maxrate) + maxrate = j; + } + } + +#if 0 + if (ic->ic_curmode == IEEE80211_MODE_11NG) + raid = R92C_RAID_11GN; +#endif + /* NB: group addressed frames are done at 11bg rates for now */ if (ic->ic_curmode == IEEE80211_MODE_11B) mode = R92C_RAID_11B; else @@ -1874,7 +1933,9 @@ "could not add broadcast station\n"); return (error); } + /* Set initial MRR rate. */ + /* XXX TODO: should use the 11n rate here if necessary? */ URTWN_DPRINTF(sc, URTWN_DEBUG_RA, "%s: maxbasicrate %d\n", __func__, maxbasicrate); urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BC), @@ -1881,6 +1942,12 @@ maxbasicrate); /* Set rates mask for unicast frames. */ + if (ni->ni_flags & IEEE80211_NODE_HT) + mode = R92C_RAID_11GN; + if (ic->ic_curmode == IEEE80211_MODE_11B) + mode = R92C_RAID_11B; + else + mode = R92C_RAID_11BG; cmd.macid = URTWN_MACID_BSS | URTWN_MACID_VALID; cmd.mask = htole32(mode << 28 | rates); error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); @@ -1896,6 +1963,7 @@ maxrate); /* Indicate highest supported rate. */ + /* XXX TODO: this is wrong for 11n */ ni->ni_txrate = rs->rs_rates[rs->rs_nrates - 1]; ieee80211_free_node(ni); @@ -2643,7 +2711,12 @@ static __inline uint8_t rate2ridx(uint8_t rate) { + if (rate & IEEE80211_RATE_MCS) { + /* 11n rates start at idx 12 */ + return ((rate & 0xf) + 12); + } switch (rate) { + /* 11g */ case 12: return 4; case 18: return 5; case 24: return 6; @@ -2652,10 +2725,12 @@ case 72: return 9; case 96: return 10; case 108: return 11; + /* 11b */ case 2: return 0; case 4: return 1; case 11: return 2; case 22: return 3; + /* XXX TODO: 11n? */ default: return 0; } } @@ -2711,6 +2786,7 @@ (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } else { + /* XXX TODO: these are high defaults w/ no ratectl? */ if (ic->ic_curmode != IEEE80211_MODE_11B) rate = 108; else @@ -2719,7 +2795,9 @@ } ridx = rate2ridx(rate); - if (ic->ic_curmode != IEEE80211_MODE_11B) + if (ic->ic_curmode == IEEE80211_MODE_11NG) + raid = R92C_RAID_11GN; + else if (ic->ic_curmode != IEEE80211_MODE_11B) raid = R92C_RAID_11BG; else raid = R92C_RAID_11B; @@ -2763,6 +2841,7 @@ } else txd->txdw1 |= htole32(R92C_TXDW1_AGGBK); + /* XXX TODO: HT protmode */ if (ic->ic_flags & IEEE80211_F_USEPROT) { switch (ic->ic_protmode) { case IEEE80211_PROT_CTSONLY: @@ -2779,8 +2858,12 @@ break; } } + + /* XXX TODO: rtsrate is configurable? 24mbit may + * be a bit high for RTS rate? */ txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, URTWN_RIDX_OFDM24)); + txd->txdw5 |= htole32(0x0001ff00); } else /* IEEE80211_FC0_TYPE_MGT */ qsel = R92C_TXDW1_QSEL_MGNT; @@ -2793,6 +2876,11 @@ SM(R92C_TXDW1_QSEL, qsel) | SM(R92C_TXDW1_RAID, raid)); + /* XXX TODO: 40MHZ flag? */ + /* XXX TODO: AMPDU flag? (AGG_ENABLE or AGG_BREAK?) Density shift? */ + /* XXX Short preamble? */ + /* XXX Short-GI? */ + if (sc->chip & URTWN_CHIP_88E) txd->txdw1 |= htole32(SM(R88E_TXDW1_MACID, macid)); else @@ -2799,6 +2887,7 @@ txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, macid)); txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); + /* Force this rate if needed. */ if (URTWN_CHIP_HAS_RATECTL(sc) || ismcast || (m->m_flags & M_EAPOL) || type != IEEE80211_FC0_TYPE_DATA) @@ -2888,6 +2977,8 @@ } } + /* XXX TODO: 11n checks, matching urtwn_tx_data() */ + wh = mtod(m, struct ieee80211_frame *); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; @@ -2916,6 +3007,7 @@ else txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, URTWN_MACID_BC)); + /* XXX TODO: rate index/config (RAID) for 11n? */ txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT)); txd->txdw1 |= htole32(SM(R92C_TXDW1_CIPHER, cipher));