diff options
Diffstat (limited to 'sys/dev/rtwn/if_rtwn.c')
-rw-r--r-- | sys/dev/rtwn/if_rtwn.c | 140 |
1 files changed, 134 insertions, 6 deletions
diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index 4334d5700e51..7a547e13cafa 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -232,6 +232,7 @@ rtwn_attach(struct rtwn_softc *sc) | IEEE80211_C_WME /* 802.11e */ | IEEE80211_C_SWAMSDUTX /* Do software A-MSDU TX */ | IEEE80211_C_FF /* Atheros fast-frames */ + | IEEE80211_C_TXPMGT /* TX power control */ ; if (sc->sc_hwcrypto != RTWN_CRYPTO_SW) { @@ -247,6 +248,7 @@ rtwn_attach(struct rtwn_softc *sc) | IEEE80211_HTCAP_SMPS_OFF /* SM PS mode disabled */ /* s/w capabilities */ | IEEE80211_HTC_HT /* HT operation */ + | IEEE80211_HTC_RX_AMSDU_AMPDU /* A-MSDU in A-MPDU */ | IEEE80211_HTC_AMPDU /* A-MPDU tx */ | IEEE80211_HTC_AMSDU /* A-MSDU tx */ ; @@ -296,6 +298,11 @@ rtwn_attach(struct rtwn_softc *sc) sc->sc_node_free = ic->ic_node_free; ic->ic_node_free = rtwn_node_free; + /* Note: this has to happen AFTER ieee80211_ifattach() */ + ieee80211_set_software_ciphers(ic, IEEE80211_CRYPTO_WEP | + IEEE80211_CRYPTO_TKIP | IEEE80211_CRYPTO_AES_CCM | + IEEE80211_CRYPTO_AES_GCM_128); + rtwn_postattach(sc); rtwn_radiotap_attach(sc); @@ -319,18 +326,55 @@ rtwn_radiotap_attach(struct rtwn_softc *sc) &rxtap->wr_ihdr, sizeof(*rxtap), RTWN_RX_RADIOTAP_PRESENT); } +#ifdef RTWN_DEBUG +static int +rtwn_sysctl_reg_readwrite(SYSCTL_HANDLER_ARGS) +{ + struct rtwn_softc *sc = arg1; + int error; + uint32_t val; + + if (sc->sc_reg_addr > 0xffff) + return (EINVAL); + + RTWN_LOCK(sc); + val = rtwn_read_4(sc, sc->sc_reg_addr); + RTWN_UNLOCK(sc); + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return (error); + RTWN_LOCK(sc); + rtwn_write_4(sc, sc->sc_reg_addr, val); + RTWN_UNLOCK(sc); + return (0); +} +#endif /* RTWN_DEBUG */ + void rtwn_sysctlattach(struct rtwn_softc *sc) { struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); -#if 1 + sc->sc_reg_addr = 0; +#ifdef RTWN_DEBUG + SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "reg_addr", CTLFLAG_RW, &sc->sc_reg_addr, + sc->sc_reg_addr, "debug register address"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "reg_val", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + rtwn_sysctl_reg_readwrite, "I", "debug register read/write"); +#endif /* RTWN_DEBUG */ + sc->sc_ht40 = 0; SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "ht40", CTLFLAG_RDTUN, &sc->sc_ht40, sc->sc_ht40, "Enable 40 MHz mode support"); -#endif + + sc->sc_ena_tsf64 = 0; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ena_tsf64", CTLFLAG_RWTUN, &sc->sc_ena_tsf64, + sc->sc_ena_tsf64, "Enable/disable per-packet TSF64 reporting"); #ifdef RTWN_DEBUG SYSCTL_ADD_U32(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, @@ -397,6 +441,29 @@ rtwn_resume(struct rtwn_softc *sc) ieee80211_resume_all(ic); } +void +rtwn_attach_vht_cap_info_mcs(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t rx_mcs = 0, tx_mcs = 0; + + for (int i = 0 ; i < 8; i++) { + if (i < sc->ntxchains) + tx_mcs |= (IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2)); + else + tx_mcs |= (IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); + + if (i < sc->nrxchains) + rx_mcs |= (IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2)); + else + rx_mcs |= (IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2)); + } + ic->ic_vht_cap.supp_mcs.rx_mcs_map = rx_mcs; + ic->ic_vht_cap.supp_mcs.rx_highest = 0; + ic->ic_vht_cap.supp_mcs.tx_mcs_map = tx_mcs; + ic->ic_vht_cap.supp_mcs.tx_highest = 0; +} + static void rtwn_vap_decrement_counters(struct rtwn_softc *sc, enum ieee80211_opmode opmode, int id) @@ -570,6 +637,7 @@ rtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, /* 802.11n parameters */ vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_16; vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + vap->iv_ampdu_limit = IEEE80211_HTCAP_MAXRXAMPDU_64K; TIMEOUT_TASK_INIT(taskqueue_thread, &uvp->tx_beacon_csa, 0, rtwn_tx_beacon_csa, vap); @@ -691,6 +759,14 @@ rtwn_ioctl_reset(struct ieee80211vap *vap, u_long cmd) case IEEE80211_IOC_LDPC: error = 0; break; + case IEEE80211_IOC_TXPOWER: + { + struct rtwn_softc *sc = vap->iv_ic->ic_softc; + RTWN_LOCK(sc); + error = rtwn_set_tx_power(sc, vap); + RTWN_UNLOCK(sc); + } + break; default: error = ENETRESET; break; @@ -954,6 +1030,8 @@ rtwn_tsf_sync_enable(struct rtwn_softc *sc, struct ieee80211vap *vap) /* Enable TSF synchronization. */ rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id), R92C_BCN_CTRL_DIS_TSF_UDT0, 0); + /* Enable TSF beacon handling, needed for RA */ + rtwn_sta_beacon_enable(sc, uvp->id, true); break; case IEEE80211_M_IBSS: ieee80211_runtask(ic, &uvp->tsf_sync_adhoc_task); @@ -1095,6 +1173,7 @@ rtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* Disable TSF synchronization / beaconing. */ rtwn_beacon_enable(sc, uvp->id, 0); + rtwn_sta_beacon_enable(sc, uvp->id, false); rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id), 0, R92C_BCN_CTRL_DIS_TSF_UDT0); @@ -1124,6 +1203,9 @@ rtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* Stop Rx of data frames. */ rtwn_write_2(sc, R92C_RXFLTMAP2, 0); + /* Stop Rx of control frames. */ + rtwn_write_2(sc, R92C_RXFLTMAP1, 0); + /* Reset EDCA parameters. */ rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3217); rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4317); @@ -1188,7 +1270,8 @@ rtwn_calc_basicrates(struct rtwn_softc *sc) struct rtwn_vap *rvp; struct ieee80211vap *vap; struct ieee80211_node *ni; - uint32_t rates; + struct ieee80211_htrateset *rs_ht; + uint32_t rates = 0, htrates = 0; rvp = sc->vaps[i]; if (rvp == NULL || rvp->curr_mode == R92C_MSR_NOLINK) @@ -1199,16 +1282,48 @@ rtwn_calc_basicrates(struct rtwn_softc *sc) continue; ni = ieee80211_ref_node(vap->iv_bss); - rtwn_get_rates(sc, &ni->ni_rates, NULL, &rates, NULL, 1); + if (ni->ni_flags & IEEE80211_NODE_HT) + rs_ht = &ni->ni_htrates; + else + rs_ht = NULL; + /* + * Only fetches basic rates; fetch 802.11abg and 11n basic + * rates + */ + rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &htrates, + NULL, 1); + + /* + * We need at least /an/ OFDM and/or MCS rate for HT + * operation, or the MAC will generate MCS7 ACK/Block-ACK + * frames and thus performance will suffer. + */ + if (ni->ni_flags & IEEE80211_NODE_HT) { + htrates |= 0x01; /* MCS0 */ + rates |= (1 << RTWN_RIDX_OFDM6); + } + basicrates |= rates; + basicrates |= (htrates << RTWN_RIDX_HT_MCS_SHIFT); + + /* Filter out undesired high rates */ + if (ni->ni_chan != IEEE80211_CHAN_ANYC && + IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) + basicrates &= R92C_RRSR_RATE_MASK_5GHZ; + else + basicrates &= R92C_RRSR_RATE_MASK_2GHZ; + ieee80211_free_node(ni); } - if (basicrates == 0) + if (basicrates == 0) { + device_printf(sc->sc_dev, + "WARNING: no configured basic rates!\n"); return; + } - /* XXX initial RTS rate? */ rtwn_set_basicrates(sc, basicrates); + rtwn_set_rts_rate(sc, basicrates); } static int @@ -1262,6 +1377,11 @@ rtwn_run(struct rtwn_softc *sc, struct ieee80211vap *vap) rtwn_write_2(sc, R92C_BCN_INTERVAL(uvp->id), ni->ni_intval); if (sc->vaps_running == sc->monvaps_running) { + /* Enable Rx of BAR control frames. */ + rtwn_write_2(sc, R92C_RXFLTMAP1, + 1 << (IEEE80211_FC0_SUBTYPE_BAR >> + IEEE80211_FC0_SUBTYPE_SHIFT)); + /* Enable Rx of data frames. */ rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); @@ -1539,6 +1659,14 @@ rtwn_getradiocaps(struct ieee80211com *ic, /* XXX workaround add_channel_list() limitations */ setbit(bands, IEEE80211_MODE_11A); setbit(bands, IEEE80211_MODE_11NA); + + if (IEEE80211_CONF_VHT(ic)) { + setbit(bands, IEEE80211_MODE_VHT_5GHZ); + /* Only enable VHT80 if HT40/VHT40 is available */ + if (sc->sc_ht40) + cbw_flags |= NET80211_CBW_FLAG_VHT80; + } + for (i = 0; i < nitems(sc->chan_num_5ghz); i++) { if (sc->chan_num_5ghz[i] == 0) continue; |